bzoj4384[POI2015]Trzy wieże

bzoj4384[POI2015]Trzy wieże

题意:

给定一个长度为n的仅包含'B'、'C'、'S'三种字符的字符串,请找到最长的一段连续子串,使得这一段要么只有一种字符,要么有多种字符,但是没有任意两种字符出现次数相同。

题解:

恶心的树状数组题。首先先求出只有一种字符的最长字串。然后预处理出前缀和。题目要求满足

cnt[1][i]-cnt[1][j]!=cnt[2][i]-cnt[2][j] cnt[2][i]-cnt[2][j]!=cnt[3][i]-cnt[3][j] cnt[1][i]-cnt[1][j]!=cnt[3][i]-cnt[3][j]

化简得到cnt[1][i]-cnt[2][i]!=cnt[1][j]-cnt[2][j] cnt[2][i]-cnt[3][i]!=cnt[2][j]-cnt[3][j] cnt[1][i]-cnt[3][i]!=cnt[1][j]-cnt[3][j]

把cnt[1][i]-cnt[2][i],cnt[2][i]-cnt[3][i],cnt[1][i]-cnt[3][i]分别当成xi,yi,zi,题目就转化成对每个i,求一个j使它们的xyz不同且i与j相差最大。首先以x为关键字排序,接着以y(离散化除掉负数,用链表法,如果用排序法会T)为下标建树状数组,树状数组维护6个值:之前处理过的位置的最大最小值、最大最小值对应的z,与最大最小值的z不同的最大最小值。为什么要维护最小值呢?因为按x排序后位置先后顺序会不一样,可能会出现位置靠后的比位置靠前先处理的情况。使x不同的具体方法,就是对于x相同的一组位置,先对它们一起分别查询更新答案,更新答案完后再一起分别插入树状数组。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 1000010
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define lb(x) x&-x
 7 #define INF 0x3fffffff
 8 using namespace std;
 9 
10 struct nd{int id,cnt[3];}; nd nds[maxn]; struct e{int v,n;}; int ess,g[maxn<<1]; e es[maxn];
11 void pe(int a,int b){es[++ess]=(e){a,g[b]}; g[b]=ess;}
12 int ans,n,tot; char s[maxn];
13 struct bit{int mn1,mnz,mn2,mx1,mxz,mx2;}; bit bits1[maxn],bits2[maxn];
14 bool cmp1(nd a,nd b){return a.cnt[0]<b.cnt[0];}
15 void query1(nd a){
16     int b=a.cnt[1]-1;
17     while(b){
18         if(bits1[b].mnz==a.cnt[2]){
19             if(bits1[b].mn2!=INF)ans=max(ans,a.id-bits1[b].mn2);
20         }else if(bits1[b].mn1!=INF)ans=max(ans,a.id-bits1[b].mn1);
21         if(bits1[b].mxz==a.cnt[2]){
22             if(bits1[b].mx2!=0)ans=max(ans,bits1[b].mx2-a.id);
23         }else if(bits1[b].mx1!=0)ans=max(ans,bits1[b].mx1-a.id);
24         b-=lb(b);
25     }
26 }
27 void query2(nd a){
28     int b=a.cnt[1]+1;
29     while(b<=tot){
30         if(bits2[b].mnz==a.cnt[2]){
31             if(bits1[b].mn2!=INF)ans=max(ans,a.id-bits2[b].mn2);
32         }else if(bits2[b].mn1!=INF)ans=max(ans,a.id-bits2[b].mn1);
33         if(bits2[b].mxz==a.cnt[2]){
34             if(bits1[b].mx2!=0)ans=max(ans,bits2[b].mx2-a.id);
35         }else if(bits2[b].mx1!=0)ans=max(ans,bits2[b].mx1-a.id);
36         b+=lb(b);
37     }
38 }
39 void update1(nd a){
40     int b=a.cnt[1];
41     while(b<=tot){
42         if(a.id<bits1[b].mn1){
43             if(a.cnt[2]!=bits1[b].mnz)
44                 bits1[b].mnz=a.cnt[2],bits1[b].mn2=bits1[b].mn1,bits1[b].mn1=a.id;
45             else bits1[b].mn1=a.id;
46         }else if(a.cnt[2]!=bits1[b].mnz&&a.id<bits1[b].mn2)bits1[b].mn2=a.id;
47         if(a.id>bits1[b].mx1){
48             if(a.cnt[2]!=bits1[b].mxz)
49                 bits1[b].mxz=a.cnt[2],bits1[b].mx2=bits1[b].mx1,bits1[b].mx1=a.id;
50             else bits1[b].mx1=a.id;
51         }else if(a.cnt[2]!=bits1[b].mxz&&a.id>bits1[b].mx2)bits1[b].mx2=a.id;
52         b+=lb(b);
53     }
54 }
55 void update2(nd a){
56     int b=a.cnt[1];
57     while(b){
58         if(a.id<bits2[b].mn1){
59             if(a.cnt[2]!=bits2[b].mnz)
60                 bits2[b].mnz=a.cnt[2],bits2[b].mn2=bits2[b].mn1,bits2[b].mn1=a.id;
61             else bits2[b].mn1=a.id;
62         }else if(a.cnt[2]!=bits2[b].mnz&&a.id<bits2[b].mn2)bits2[b].mn2=a.id;
63         if(a.id>bits2[b].mx1){
64             if(a.cnt[2]!=bits2[b].mxz)
65                 bits2[b].mxz=a.cnt[2],bits2[b].mx2=bits2[b].mx1,bits2[b].mx1=a.id;
66             else bits2[b].mx1=a.id;
67         }else if(a.cnt[2]!=bits2[b].mxz&&a.id>bits2[b].mx2)bits2[b].mx2=a.id;
68         b-=lb(b);
69     }
70 }
71 int main(){
72     scanf("%d",&n); scanf("%s",s+1); int cnt[3]={0,0,0};
73     int l=1,r=1; while(r<=n){while(r<=n&&s[l]==s[r])ans=max(ans,r-l+1),r++; l++;}
74     nds[0]=(nd){0,{0,0,0}};
75     inc(i,1,n){
76         if(s[i]=='B')cnt[0]++; if(s[i]=='C')cnt[1]++; if(s[i]=='S')cnt[2]++;
77         nds[i]=(nd){i,{cnt[0]-cnt[1],cnt[0]-cnt[2],cnt[1]-cnt[2]}};
78     }
79     ess=0; inc(i,0,n)pe(i,nds[i].cnt[1]+n+1); tot=0;
80     inc(i,0,n*2+1)if(g[i]){
81         tot++; int x=g[i]; while(x)nds[es[x].v].cnt[1]=tot,x=es[x].n;
82     }
83     inc(i,1,tot)bits1[i]=bits2[i]=(bit){INF,0,INF,0,0,0}; sort(nds,nds+n+1,cmp1); int i=0;
84     while(i<=n){
85         int j=i; while(j<=n&&nds[j].cnt[0]==nds[i].cnt[0])j++;
86         if(i)inc(k,i,j-1){query1(nds[k]); query2(nds[k]);}
87         inc(k,i,j-1){update1(nds[k]); update2(nds[k]);}
88         i=j;
89     }
90     printf("%d",ans); return 0;
91 }

 

20160627

posted @ 2016-07-30 13:09  YuanZiming  阅读(334)  评论(0编辑  收藏  举报