1. 程式人生 > >P2787 語文1(chin1)- 理理思維

P2787 語文1(chin1)- 理理思維

考試 code pda 神奇 模擬 strong nod 直接 個數字

題目背景

蒟蒻HansBug在語文考場上,撓了無數次的頭,可腦子裏還是一片空白。

題目描述

考試開始了,可是蒟蒻HansBug腦中還是一片空白。哦不!準確的說是亂七八糟的。現在首要任務就是幫蒟蒻HansBug理理思維。假設HansBug的思維是一長串字符串(字符串中包含且僅包含26個字母),現在的你,有一張神奇的藥方,上面依次包含了三種操作:

  1. 獲取第x到第y個字符中字母k出現了多少次

  2. 將第x到第y個字符全部賦值為字母k

  3. 將第x到第y個字符按照A-Z的順序排序

你欣喜若狂之時,可是他腦細胞和RP已經因為之前過度緊張消耗殆盡,眼看試卷最後還有一篇800字的作文呢,所以這個關鍵的任務就交給你啦!

輸入輸出格式

輸入格式:

第一行包含兩個整數N、M,分別表示HansBug的思維所包含的字母個數和藥方上操作個數。

第二行包含一個長度為N的字符串,表示HansBug的思維。

第3-M+2行每行包含一條操作,三種操作格式如下:

  1. 操作1: 1 xi yi ki 表示將第xi到第yi個字符中ki出現的次數輸出

  2. 操作2: 2 xi yi ki 表示將第xi到第yi個字符全部替換為ki

  3. 操作3: 3 xi yi 表示將第xi到第yi個字符按照A-Z的順序排序

輸出格式:

輸出為若幹行,每行包含一個整數,依次為所有操作1所得的結果。

輸入輸出樣例

輸入樣例#1:
10 5
ABCDABCDCD
1 1 3 A
3 1 5
1 1 3 A
2 1 2 B
1 2 3 B
輸出樣例#1:
1
2
2

說明

樣例說明:

技術分享圖片

數據規模:

技術分享圖片

此題目中大小寫不敏感。

Solution:

  本題線段樹的做法實在是巧妙~~。

  理理思維,因為只有$26$個字母(忽略大小寫後),於是我們將每個字母映射為$0$到$25$的數字,可以建$26$棵線段樹來維護每個數字出現的個數(註意,千萬不要寫數組般的線段樹,不好進行第三個操作,所以最好用結構體來存。記得對結構體中成員清$0$!

由於這個我調了很久~

  講下向上維護時的$pushup$,我們這裏騷操作重載運算符$+$,將其定義為將兩個結構體變量的成員$p[]$(即維護的$26$棵線段樹)累加,返回一個結構體變量,這波操作能方便後面的$query$。那麽$pushup$就是將當前左右兒子的信息累加到當前節點就好了。

  然後我們考慮區間修改$update$操作,正常的判斷區間包含然後直接修改,這裏設置懶惰標記(初值為$-1$),每次修改後就標記,然後下放時就將左右兒子維護的數組清$0$,賦值為當前的數字所對應的長度。

  重點的查詢,我們直接返回維護當前查詢區間的結構體變量,這樣對於操作$1$,直接輸出某個$p[i]$的值即可,而對於操作$3$直接從前往後掃模擬一遍,暴力成段修改,最多也就$26$次$update$。

  那麽本題就$OK$了。

代碼:

 1 #include<bits/stdc++.h>
 2 #define lson l,m,rt<<1
 3 #define rson m+1,r,rt<<1|1
 4 #define il inline
 5 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 6 #define Max(a,b) ((a)>(b)?(a):(b))
 7 using namespace std;
 8 const int N=50005;
 9 int n,m,ss[N],lazy[N<<2];
10 char s[N];
11 struct node{
12     int p[28];
13     void cler(){memset(p,0,sizeof(p));}
14 }t[N<<2],emp;
15 node operator + (node a,node b){
16     node c;
17     For(i,0,25)c.p[i]=a.p[i]+b.p[i];
18     return c;
19 }
20 il int gi(){
21     int a=0;char x=getchar();
22     while(x<0||x>9)x=getchar();
23     while(x>=0&&x<=9)a=(a<<3)+(a<<1)+x-48,x=getchar();
24     return a;
25 }
26 il int change(char x){return (x>=a&&x<=z)?x-a:x-A;}
27 il void pushup(int rt){For(i,0,25)t[rt].p[i]=t[rt<<1].p[i]+t[rt<<1|1].p[i];}
28 il void pushdown(int rt,int len){
29     if(lazy[rt]!=-1){
30         lazy[rt<<1]=lazy[rt],lazy[rt<<1|1]=lazy[rt];
31         t[rt<<1].cler();t[rt<<1|1].cler();
32         t[rt<<1].p[lazy[rt<<1]]=(len-(len>>1)),t[rt<<1|1].p[lazy[rt<<1|1]]=(len>>1);
33         lazy[rt]=-1;
34     }
35 }
36 il void build(int l,int r,int rt){
37     if(l==r){t[rt].cler();t[rt].p[change(s[l])]=1;return;}
38     int m=l+r>>1;
39     build(lson),build(rson);
40     pushup(rt);    
41 }
42 il void update(int L,int R,int c,int l,int r,int rt){
43     if(L<=l&&R>=r){
44         t[rt].cler(),lazy[rt]=c;
45         t[rt].p[c]=r-l+1;return;
46     }
47     int m=l+r>>1;
48     pushdown(rt,r-l+1);
49     if(L<=m)update(L,R,c,lson);
50     if(R>m)update(L,R,c,rson);
51     pushup(rt);
52 }
53 il node query(int L,int R,int l,int r,int rt){
54     if(L<=l&&R>=r)return t[rt];
55     node ret;
56     ret.cler();
57     int m=l+r>>1;
58     pushdown(rt,r-l+1);
59     if(L<=m)ret=ret+query(L,R,lson);
60     if(R>m)ret=ret+query(L,R,rson);
61     return ret;
62 }
63 int main(){
64     n=gi(),m=gi();
65     scanf("%s",s+1);
66     memset(lazy,-1,sizeof(lazy));
67     build(1,n,1);
68     int f,x,y;char z[2];
69     while(m--){
70         f=gi();x=gi();y=gi();
71         if(f!=3)scanf("%s",z);
72         if(f==1) printf("%d\n",query(x,y,1,n,1).p[change(z[0])]);
73         else if(f==2) update(x,y,change(z[0]),1,n,1);
74         else {
75             node tmp=query(x,y,1,n,1);
76             int l,r=x-1;
77             For(i,0,25){
78                 if(!tmp.p[i])continue;
79                 l=r+1,r=l+tmp.p[i]-1;
80                 update(l,r,i,1,n,1);
81             }
82         }
83     }
84     return 0;
85 }

P2787 語文1(chin1)- 理理思維