CF-558E (线段树/分块)

Posted blog-dr-j

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF-558E (线段树/分块)相关的知识,希望对你有一定的参考价值。

解题思路:

很显然突破口就是字符集比较小,分块和线段树都能A

话说线段树时间是分块5倍啊

代码(线段树):

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll spc<<1
  5 #define rrr spc<<1|1
  6 struct int_26{
  7     int has[30];
  8     void res(void)
  9     {
 10         memset(has,0,sizeof(has));
 11         return ;
 12     }
 13     int_26 friend operator + (int_26 x,int_26 y)
 14     {
 15         int_26 ans;
 16         for(int i=1;i<=26;i++)
 17             ans.has[i]=x.has[i]+y.has[i];
 18         return ans;
 19     }
 20 }isr;
 21 struct trnt{
 22     int_26 val;
 23     int lzt;
 24 }tr[1000000];
 25 int n,q;
 26 int ans[1000000];
 27 char cmd[1000000];
 28 void pushup(int spc)
 29 {
 30     tr[spc].val=tr[lll].val+tr[rrr].val;
 31     return ;
 32 }
 33 void pushdown(int spc,int l,int r)
 34 {
 35     if(tr[spc].lzt)
 36     {
 37         int mid=(l+r)>>1;
 38         tr[lll].lzt=tr[spc].lzt;
 39         tr[rrr].lzt=tr[spc].lzt;
 40         tr[spc].lzt=0;
 41         tr[lll].val.res();
 42         tr[rrr].val.res();
 43         tr[lll].val.has[tr[lll].lzt]=mid-l+1;
 44         tr[rrr].val.has[tr[rrr].lzt]=r-mid;
 45     }
 46     return ;
 47 }
 48 void build(int spc,int l,int r)
 49 {
 50     if(l==r)
 51     {
 52         tr[spc].val.has[cmd[l]-a+1]=1;
 53         return ;
 54     }
 55     int mid=(l+r)>>1;
 56     build(lll,l,mid);
 57     build(rrr,mid+1,r);
 58     pushup(spc);
 59     return ;
 60 }
 61 void update(int l,int r,int ll,int rr,int spc,int v)
 62 {
 63     if(l>rr||ll>r)
 64         return ;
 65     if(ll<=l&&r<=rr)
 66     {
 67         tr[spc].val.res();
 68         tr[spc].val.has[v]=r-l+1;
 69         tr[spc].lzt=v;
 70         return ;
 71     }
 72     int mid=(l+r)>>1;
 73     pushdown(spc,l,r);
 74     update(l,mid,ll,rr,lll,v);
 75     update(mid+1,r,ll,rr,rrr,v);
 76     pushup(spc);
 77     return ;
 78 }
 79 int_26 query(int l,int r,int ll,int rr,int spc)
 80 {
 81     if(l>rr||ll>r)
 82         return isr;
 83     if(ll<=l&&r<=rr)
 84         return tr[spc].val;
 85     int mid=(l+r)>>1;
 86     pushdown(spc,l,r);
 87     return query(l,mid,ll,rr,lll)+query(mid+1,r,ll,rr,rrr);
 88 }
 89 void S_pushdown(int l,int r,int spc)
 90 {
 91     if(l==r)
 92     {
 93         for(int i=1;i<=26;i++)
 94             if(tr[spc].val.has[i])
 95             {
 96                 ans[l]=i;
 97                 break;
 98             }
 99         return ;
100     }
101     int mid=(l+r)>>1;
102     pushdown(spc,l,r);
103     S_pushdown(l,mid,lll);
104     S_pushdown(mid+1,r,rrr);
105     return ;
106 }
107 int main()
108 {
109     scanf("%d%d",&n,&q);
110     scanf("%s",cmd+1);
111     build(1,1,n);
112     while(q--)
113     {
114         int l,r,op;
115         scanf("%d%d%d",&l,&r,&op);
116         if(l>r)
117             std::swap(l,r);
118         int_26 tmp=query(1,n,l,r,1);
119         if(op)
120         {
121             int sta=l;
122             for(int i=1;i<=26;i++)
123             {
124                 if(!tmp.has[i])
125                     continue;
126                 update(1,n,sta,sta+tmp.has[i]-1,1,i);
127                 sta+=tmp.has[i];
128             }
129         }else{
130             int sta=l;
131             for(int i=26;i;i--)
132             {
133                 if(!tmp.has[i])
134                     continue;
135                 update(1,n,sta,sta+tmp.has[i]-1,1,i);
136                 sta+=tmp.has[i];
137             }
138         }
139     }
140     S_pushdown(1,n,1);
141     for(int i=1;i<=n;i++)
142         printf("%c",ans[i]+a-1);
143     return 0;
144 }

代码(分块):

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 struct Area{
  6     int l,r;
  7     int lzt;//1 shenx -1 jiangx 0 wu
  8     int has[30];
  9 }p[200000];
 10 int n,q;
 11 int a[200000];
 12 int blg[200000];
 13 int tmp[30];
 14 char cmd[1000000];
 15 bool cmp(int x,int y)
 16 {
 17     return x<y;
 18 }//shenx
 19 bool cmq(int x,int y)
 20 {
 21     return x>y;
 22 }//jiangx
 23 void P_sort(int x)
 24 {
 25     if(!p[x].lzt)
 26         return ;
 27     if(p[x].lzt==1)
 28     {
 29         int t=1;
 30         for(int i=p[x].l;i<=p[x].r;i++)
 31         {
 32             while(!p[x].has[t])
 33                 t++;
 34             a[i]=t;
 35             p[x].has[t]--;
 36         }
 37     }
 38     if(p[x].lzt==-1)
 39     {
 40         int t=26;
 41         for(int i=p[x].l;i<=p[x].r;i++)
 42         {
 43             while(!p[x].has[t])
 44                 t--;
 45             a[i]=t;
 46             p[x].has[t]--;
 47         }
 48     }
 49     p[x].lzt=0;
 50     return ;
 51 }
 52 void build(int x)
 53 {
 54     for(int i=1;i<=26;i++)
 55         p[x].has[i]=0;
 56     for(int i=p[x].l;i<=p[x].r;i++)
 57         p[x].has[a[i]]++;
 58     return ;
 59 }
 60 int main()
 61 {
 62     scanf("%d%d",&n,&q);
 63     if(n<=1000)
 64     {
 65         scanf("%s",cmd+1);
 66         for(int i=1;i<=n;i++)
 67             a[i]=cmd[i]-a+1;
 68         for(int i=1;i<=q;i++)
 69         {
 70             int l,r,op;
 71             scanf("%d%d%d",&l,&r,&op);
 72             if(l>r)
 73                 std::swap(l,r);
 74             if(op==0)
 75                 std::sort(a+l,a+r+1,cmq);
 76             else
 77                 std::sort(a+l,a+r+1,cmp);
 78         }
 79         for(int i=1;i<=n;i++)
 80             printf("%c",a[i]+a-1);
 81         puts("");
 82         return 0;
 83     }
 84     scanf("%s",cmd+1);
 85     int stan=(sqrt(n));
 86     for(int i=1;i<=n;i++)
 87     {
 88         a[i]=cmd[i]-a+1;
 89         blg[i]=i/stan+1;
 90         p[blg[i]].has[a[i]]++;
 91         if(blg[i]!=blg[i-1])
 92         {
 93             p[blg[i]].l=i;
 94             p[blg[i-1]].r=i-1;
 95         }
 96     }
 97     p[blg[n]].r=n;
 98     while(q--)
 99     {
100         int l,r,op;
101         scanf("%d%d%d",&l,&r,&op);
102         if(l>r)
103             std::swap(l,r);
104         if(blg[l]==blg[r])
105         {
106             if(op==0)
107                 std::sort(a+l,a+r+1,cmq);
108             else
109                 std::sort(a+l,a+r+1,cmp);
110             continue;
111         }
112         memset(tmp,0,sizeof(tmp));
113         P_sort(blg[l]);
114         build(blg[l]);
115         P_sort(blg[r]);
116         build(blg[r]);
117         for(int i=l;i<=p[blg[l]].r;i++)
118             tmp[a[i]]++;
119         for(int i=p[blg[r]].l;i<=r;i++)
120             tmp[a[i]]++;
121         for(int i=1;i<=26;i++)
122             for(int j=blg[l]+1;j<=blg[r]-1;j++)
123                 tmp[i]+=p[j].has[i];
124         if(op==0)
125         {
126             int t=26;
127             for(int i=l;i<=p[blg[l]].r;i++)
128             {
129                 while(!tmp[t])
130                     t--;
131                 tmp[t]--;
132                 a[i]=t;
133             }
134             build(blg[l]);
135             for(int i=blg[l]+1;i<=blg[r]-1;i++)
136             {
137                 int len=p[i].r-p[i].l+1;
138                 for(int j=1;j<=26;j++)
139                     p[i].has[j]=0;
140                 while(tmp[t]<len)
141                 {
142                     p[i].has[t]+=tmp[t];
143                     len-=tmp[t];
144                     tmp[t]=0;
145                     t--;
146                 }
147                 if(len)
148                 {
149                     p[i].has[t]+=len;
150                     tmp[t]-=len;
151                     if(!tmp[t])
152                         t--;
153                 }
154                 p[i].lzt=-1;
155             }
156             for(int i=p[blg[r]].l;i<=r;i++)
157             {
158                 while(!tmp[t])
159                     t--;
160                 tmp[t]--;
161                 a[i]=t;
162             }
163             build(blg[r]);
164         }else{
165             int t=1;
166             for(int i=l;i<=p[blg[l]].r;i++)
167             {
168                 while(!tmp[t])
169                     t++;
170                 tmp[t]--;
171                 a[i]=t;
172             }
173             build(blg[l]);
174             for(int i=blg[l]+1;i<=blg[r]-1;i++)
175             {
176                 int len=p[i].r-p[i].l+1;
177                 for(int j=1;j<=26;j++)
178                     p[i].has[j]=0;
179                 while(tmp[t]<len)
180                 {
181                     p[i].has[t]+=tmp[t];
182                     len-=tmp[t];
183                     tmp[t]=0;
184                     t++;
185                 }
186                 if(len)
187                 {
188                     p[i].has[t]+=len;
189                     tmp[t]-=len;
190                     if(!tmp[t])
191                         t++;
192                 }
193                 p[i].lzt=1;
194             }
195             for(int i=p[blg[r]].l;i<=r;i++)
196             {
197                 while(!tmp[t])
198                     t++;
199                 tmp[t]--;
200                 a[i]=t;
201             }
202             build(blg[r]);
203         }
204     }
205     for(int i=1;i<=blg[n];i++)
206         P_sort(i);
207     for(int i=1;i<=n;i++)
208         printf("%c",a[i]+a-1);
209     puts("");
210     return 0;
211 }

 

以上是关于CF-558E (线段树/分块)的主要内容,如果未能解决你的问题,请参考以下文章

[CF558E]A Simple Task

CF558E A Simple Task

骗分大法之-----分块||迷之线段树例题a

hdu 4366 Successor - CDQ分治 - 线段树 - 树分块

计蒜客16492 building(二分线段树/分块)

魔性の分块 | | jzoj1243 | | 线段树の暴力