hiho一下 第六十一週 題目1 : Combination Lock 線段樹 成段更新

時間限制:10000ms
單點時限:1000ms
內存限制:256MB

描述


Finally, you come to the interview room. You know that a Microsoft interviewer is in the room though the door is locked. There is a combination lock on the door. There are N rotators on the lock, each consists of 26 alphabetic characters, namely, 'A'-'Z'. You need to unlock the door to meet the interviewer inside. There is a note besides the lock, which shows the steps to unlock it.

Note: There are M steps totally; each step is one of the four kinds of operations shown below:

Type1: CMD 1 i j X: (i and j are integers, 1 <= i <= j <= N; X is a character, within 'A'-'Z')

This is a sequence operation: turn the ith to the jth rotators to character X (the left most rotator is defined as the 1st rotator)

For example: ABCDEFG => CMD 1 2 3 Z => AZZDEFG

Type2: CMD 2 i j K: (i, j, and K are all integers, 1 <= i <= j <= N)

This is a sequence operation: turn the ith to the jth rotators up K times ( if character A is turned up once, it is B; if Z is turned up once, it is A now. )

For example: ABCDEFG => CMD 2 2 3 1 => ACDDEFG

Type3: CMD 3 K: (K is an integer, 1 <= K <= N)

This is a concatenation operation: move the K leftmost rotators to the rightmost end.

For example: ABCDEFG => CMD 3 3 => DEFGABC

Type4: CMD 4 i j(i, j are integers, 1 <= i <= j <= N):

This is a recursive operation, which means:

If i > j:
	Do Nothing
Else:
	CMD 4 i+1 j
	CMD 2 i j 1

For example: ABCDEFG => CMD 4 2 3 => ACEDEFG

輸入

1st line:  2 integers, N, M ( 1 <= N <= 50000, 1 <= M <= 50000 )

2nd line: a string of N characters, standing for the original status of the lock.

3rd ~ (3+M-1)th lines: each line contains a string, representing one step.

輸出

One line of N characters, showing the final status of the lock.

提示

Come on! You need to do these operations as fast as possible.


樣例輸入
7 4
ABCDEFG
CMD 1 2 5 C
CMD 2 3 7 4
CMD 3 3
CMD 4 1 7
樣例輸出
HIMOFIN
題意,給出一段字符串,給出四個操作

1.把區間全改成某個字符。

2.把區間全加上一個數。

3.把前幾個字符移到最後面去。

4.把區間的所有的字符都加上1 2 3 ....;

對於1 2 4都是成段的更新字符串,所以可以用線段樹來做,但每3個操作,我們可以把整個字符串,看成是一個環形的字符串,這樣的話,我們只要改變了頭的位置,就相當於移動了字符串的位置,複雜度o(1)完成,對於 1 2 4,可以這樣設計線段樹,定義node

struct node{
    int sum,add,sadd,num,val;
};

分別表示,是否要全刷新爲一個字符串,當前段要加的值,當前段要遞增加的值,num爲等差數的公差,也就是說,第一個,加上sadd ,第二個加上 sadd + num,第三個,加上sadd + 2 * num ,依此類推,由於等差數列加上一個等差數列,依然是一個等差數列,所以這裏,可以 只用改動sadd num的值就可以表示一個等差數列的值了。val爲當前的值。注意一個問題,就是第1個操作和第34操作是有時間的衝突的,也就是說1 和3 4 是有時間的對應的關係的,就應該先更新第1個操作的值,傳遞下去之後,才應該更新其它的操作。

總的複雜度爲線段樹的操作,o(m * log(n));

這裏給出一些測試數據。可以說,向下傳遞的時候,這裏是最複雜的。

7 7
ABCDEFG
CMD 3 3
CMD 4 1 7
CMD 1 2 5 C
CMD 2 3 7 4
CMD 3 2
CMD 1 2 5 C
CMD 2 3 7 4

3 2
AAA
CMD 1 1 3 C
CMD 2 1 3 1

#define N 50005
#define M 100005
#define maxn 205
#define MOD 1000000000000000007


#define lson (now<<1)
#define rson (now<<1|1)
struct node{
    int sum,add,sadd,num,val;
};
node tree[N*8];
void update(int & x,int y){
    x += y;
    x %= 26;
}
void pushDown(int now,int l,int r){
    if(l == r){
        return ;
    }
    if(tree[now].sum >= 0){
        tree[lson].val = tree[lson].sum = tree[now].sum;
        tree[rson].val = tree[rson].sum = tree[now].sum;
        tree[now].sum = -1;
        tree[rson].add = tree[lson].add = 0;
        tree[rson].sadd = tree[lson].sadd = 0;
        tree[rson].num =tree[lson].num  = 0;
    }
    if(tree[now].add >= 0){
        update(tree[lson].add,tree[now].add);
        update(tree[rson].add,tree[now].add);
        tree[now].add = 0;
    }
    if(tree[now].sadd >= 0){
        update(tree[lson].sadd,tree[now].sadd);
        update(tree[lson].num,tree[now].num);
        update(tree[rson].sadd,tree[now].sadd + ((r - l) / 2 + 1) * tree[now].num);
        update(tree[rson].num,tree[now].num);
        tree[now].sadd = 0;
        tree[now].num = 0;
    }
}
void buildTree(int l,int r,int now){
    tree[now].sum = -1;tree[now].val = 0;tree[now].add = tree[now].sadd = tree[now].num = 0;
    if(l >= r){
        return ;
    }
    int mid = (l+r)>>1;
    buildTree(l,mid,lson);
    buildTree(mid+1,r,rson);
}
void updateTree(int l,int r,int now,int s,int e,int c,int add){
    pushDown(now,l,r);
    if(s <= l && e>= r){
        if(c == 2){
            update(tree[now].add,add);
        }
        else if(c == 4){
            update(tree[now].sadd,l - s + add);
            update(tree[now].num,1);
        }
        else  if(c == 1){
            tree[now].sum = add;
            tree[now].val = add;
            tree[now].add = tree[now].sadd = tree[now].num = 0;
        }
        return ;
    }
    int mid = (l+r)>>1;
    if(s <= mid) updateTree(l,mid,lson,s,e,c,add);
    if(e > mid) updateTree(mid+1,r,rson,s,e,c,add);
}
int queryTree(int l,int r,int now,int s,int e){
    pushDown(now,l,r);
    if(s <= l && e>= r){
        return (tree[now].val + tree[now].add + tree[now].sadd) % 26;
    }
    int mid = (l+r)>>1;
    if(s <= mid) return queryTree(l,mid,lson,s,e);
    if(e > mid) return queryTree(mid+1,r,rson,s,e);
    return 0;
}

int n,m,q,k,top;
char str[N],str2[40];
void getSe(int s,int e,int & s1,int & e1,int & s2,int & e2){
    s--;e--;
    s1 = s2 = e1 = e2 = -2;
    int t1 = top + s,t2 = top + e;
    if(t1 < n && t2 < n){
        s1 = t1;e1 = t2;
        s2 = e2 = -2;
    }
    else if(t1 < n && t2 >= n){
        t2 %= n;
        s1 = t1;e1 = n - 1;
        s2 = 0;e2 = t2;
    }
    else if(t1 >= n && t2 >= n){
        t1 %= n;t2 %= n;
        s1 = t1;e1 = t2;
        s2 = e2 = -2;
    }
    s1++;e1++;s2++;e2++;
}
void outputStr(){
    int t = top;
    For(i,1,n+1){
        printf("%c",'A' + queryTree(1,n,1,t+1,t+1));
        t++;
        t %= n;
    }
    printf("\n");
}
int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
     while(S2(n,m)!=EOF)
    {
        SS(str);
        top = 0;
        buildTree(1,n,1);
        FI(n){
            updateTree(1,n,1,i+1,i+1,1,str[i] - 'A');
        }
        FI(m){
           SS(str2);
           S(q);
           int s,e,s1,e1,s2,e2;
           if(q == 1){
                S2(s,e);SS(str2);
                getSe(s,e,s1,e1,s2,e2);
                updateTree(1,n,1,s1,e1,1,str2[0] - 'A');
                if(s2 != -1 && e2 != -1)
                updateTree(1,n,1,s2,e2,1,str2[0] - 'A');
           }
           else if(q == 2){
                S2(s,e);S(k);
                k %= 26;
                getSe(s,e,s1,e1,s2,e2);
                updateTree(1,n,1,s1,e1,2,k);
                if(s2 != -1 && e2 != -1)
                updateTree(1,n,1,s2,e2,2,k);
           }
           else if(q == 3){
                S(s);
                top += s;
                top %= n;
           }
           else if(q == 4){
                S2(s,e);
                getSe(s,e,s1,e1,s2,e2);
                updateTree(1,n,1,s1,e1,4,1);
                if(s2 != -1 && e2 != -1)
                updateTree(1,n,1,s2,e2,4,e1 - s1 + 2);
           }
        }
        outputStr();
    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章