CDOJ-1944:Letter Kingdom(DFS预处理+线段树)

Letter Kingdom
Time Limit: 2000 MS Memory Limit: 256 MB

One day, you had a dream. In the dream, you got trapped in the Letter Kingdom. Two soldiers caught you, and brought you to the front of the king.

The king asked you: “Are you a programmer?”

You answered: “Yes.”

The king said: Our Letter Kingdom is going to hold the 233rd National Day ceremony, now we need to check our traffic network, and I appoint you to be the commander of this event. Our country has n cities, numbered by the first n uppercase letters, for example the first city named A , the second city named B , and so on. Due to the lack of money, every city only has one directed road to another city. The army will arrange for m soldiers to walk between these cities. The soldiers are numbered from 1 to m . I will tell you the initial position of each soldier, and then issue three types of orders:

Interval Move: Given two integers l and r , the soldiers numbered between [ l , r ] walk along the only directed road from the current city to another city (we’ll call it Moving Operation).

Multiple Move: Given an integer x , the soldiers whose number is a multiple of x (id mod x = 0 ) do Moving Operation.

Commander Report: Given an integer p , please tell me which city the soldier numbered p located in.

Since you are a smart person, can you complete this task?

Input
The first line consists of two integers n and m , which represent the amounts of city and soldier.

The second line is a n -length string. The i t h letter in the string represents the directed road’s leading city from the i t h city. It’s guaranteed that the i t h letter in the string differs from the i t h letter in the alphabet, and the string only consists of uppercase letters.

The third line is a m -length string. The i t h letter in the string represents the i t h soldier’s initial city. The string also only consists of uppercase letters.

The fourth line consists of an integer q , which represent the number of king’s orders.

Following q lines, the first part of the line is an integer o p .

If o p = 1 , then input two integers l and r , which represent the soldiers numbered between [ l , r ] do Moving Operation.

If o p = 2 , then input an integer x , which represents the soldiers whose number is a multiple of x do Moving Operation.

If o p = 3 , then input an integer p , you should output where the soldier numbered p located in.

Its guaranteed there is at least one order that o p = 3 .

1 n 26
1 m 200000
1 q 200000
Output
For each order that o p = 3 , output the position of the soldier.

Sample input and output
Sample Input
5 6
DAEEA
AEDCBA
7
1 1 4
2 2
3 4
2 3
1 3 6
2 1
3 6
Sample Output
A
D

思路:因为最多只有26个城市,且每个城市只且仅有一条向其它城市连接的道路,所以从任意一个城市开始出发,沿着道路行走,最后都会走进一个环。
于是可以先DFS,对于任意一个作为起点城市,预处理出它走进的环的大小cyl[i],和走进环需要的距离first[i],以及走step步到达的城市nex[i][step]

对于士兵行走步数的区间更新和倍数更新。
操作1区间更新可以用树状数组或线段树记录士兵的行走步数。
至于操作2倍数更新,对于某次更新x,用lazy数组存储,即lazy[x]++,表示x的倍数的行走步数需要+1。

查询的时候,用树状数组或线段树求出操作1的步数。
sqrt(x)的方法枚举x的因子,统计操作2的步数。
求出了士兵x走的总步数后,利用DFS预处理出的信息即可求出答案。

#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
struct lenka
{
    int l,r,sum;
}A[MAX<<2];
void build(int k,int l,int r)
{
    A[k].l=l,A[k].r=r;
    A[k].sum=0;
    if(l==r)return;
    build(2*k,l,(l+r)/2);
    build(2*k+1,(l+r)/2+1,r);
}
void add(int k,int x,int y,int z)
{
    if(x==A[k].l&&y==A[k].r){A[k].sum+=z;return;}
    if(A[k].sum!=0)
    {
        add(2*k,A[2*k].l,A[2*k].r,A[k].sum);
        add(2*k+1,A[2*k+1].l,A[2*k+1].r,A[k].sum);
        A[k].sum=0;
    }
    if(y<=A[2*k].r)add(2*k,x,y,z);
    else if(x>=A[2*k+1].l)add(2*k+1,x,y,z);
    else
    {
        add(2*k,x,A[2*k].r,z);
        add(2*k+1,A[2*k+1].l,y,z);
    }
}
int ask(int k,int x)
{
    if(x==A[k].l&&x==A[k].r)return A[k].sum;
    if(A[k].sum!=0)
    {
        add(2*k,A[2*k].l,A[2*k].r,A[k].sum);
        add(2*k+1,A[2*k+1].l,A[2*k+1].r,A[k].sum);
        A[k].sum=0;
    }
    if(x<=A[2*k].r)return ask(2*k,x);
    return ask(2*k+1,x);
}
int e[30][30];
int first[30];
int cyl[30];
int nex[30][30];
int v[30];
int n;
void dfs(int k,int step,int fa)
{
    nex[fa][step]=k;
    for(int i=1;i<=n;i++)
    {
        if(e[k][i]==0)continue;
        if(v[i])
        {
            cyl[fa]=v[k]-v[i]+1;
            first[fa]=v[i]-1;
            return;
        }
        v[i]=v[k]+1;
        dfs(i,step+1,fa);
    }
}
int st[MAX];
char s[MAX];
int lazy[MAX];
int main()
{
    int m;
    cin>>n>>m;
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)e[i][s[i]-'A'+1]=1;
    for(int i=1;i<=n;i++)
    {
        memset(v,0,sizeof v);
        v[i]=1;
        dfs(i,0,i);
    }
    scanf("%s",s+1);
    for(int i=1;i<=m;i++)st[i]=s[i]-'A'+1;
    build(1,1,m);
    int T;
    cin>>T;
    while(T--)
    {
        int op;
        scanf("%d",&op);
        if(op==1)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(1,x,y,1);
        }
        if(op==2)
        {
            int x;
            scanf("%d",&x);
            lazy[x]++;
        }
        if(op==3)
        {
            int x;
            scanf("%d",&x);
            int tot=ask(1,x);
            for(int i=1;i*i<=x;i++)
            {
                if(x%i==0)
                {
                    tot+=lazy[i];
                    if(x%(x/i)==0&&x!=i*i)tot+=lazy[x/i];
                }
            }
            if(tot>first[st[x]])
            {
                tot-=first[st[x]];
                tot%=cyl[st[x]];
                tot+=first[st[x]];
            }
            tot=nex[st[x]][tot];
            printf("%c\n",tot+'A'-1);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/81051973
今日推荐