Bzoj4893 项链分赃
Submit: 89 Solved: 60
Description
有一串长度为n的项链,上面有红绿蓝三种颜色的珠子,每种颜色的珠子数目都是偶数,现在要你把它切几刀分成
若干段,把其中一些段分给海盗1,剩余的段分给海盗2,要求两个海盗分得的每种颜色的珠子数量都相同,请输出
最少需要切多少刀。
Input
第一行一个整数n,表示项链的长度。
第二行n个0~2的整数,分别表示红绿蓝三种颜色。
Output
一行一个整数,为最少切多少刀。
Sample Input
6
0 2 2 1 0 1
0 2 2 1 0 1
Sample Output
2
样例解释:切两刀,分成{0,2},{2,1,0},{1}三份,第二份给海盗1,剩下给海盗2即可。
样例解释:切两刀,分成{0,2},{2,1,0},{1}三份,第二份给海盗1,剩下给海盗2即可。
HINT
n<=100000
Source
巨大脑洞题
(开始以为“项链”是环,过了一阵子测样例才发现是链)
这题看上去不可做啊……
切一刀好说,累计前缀和,扫一遍就行;
切两刀好说,维护一个队列,队列里每种颜色数不超过一半,扫一遍就行;
切三刀……怎么搞啊?
试图乱搞,假设答案不是1就是2,WA掉了。
继续乱搞,假设答案不是1就是2就是3,A掉了。
卧槽?咋回事儿啊.jpg
然后去看了出题人的证明 http://www.cnblogs.com/juruolty/p/6806029.html
脑洞……超大啊
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 using namespace std; 7 const int mxn=100010; 8 int read(){ 9 int x=0,f=1;char ch=getchar(); 10 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 12 return x*f; 13 } 14 int n; 15 int smm[mxn][3]; 16 int now[3]; 17 int a[mxn]; 18 int main(){ 19 int i,j,x; 20 n=read(); 21 for(i=1;i<=n;i++){ 22 x=read();a[i]=x; 23 smm[i][0]=smm[i-1][0]; 24 smm[i][1]=smm[i-1][1]; 25 smm[i][2]=smm[i-1][2]; 26 ++smm[i][x]; 27 } 28 for(i=1;i<=n;i++){ 29 for(j=0;j<=2;j++){ 30 if((smm[i][j]<<1)!=smm[n][j])break; 31 } 32 if(j==3){ 33 printf("1\n"); 34 return 0; 35 } 36 } 37 int hd=1; 38 for(i=1;i<=n;i++){ 39 ++now[a[i]]; 40 for(j=0;j<=2;j++){ 41 while(hd<=i && (now[j]<<1)>smm[n][j] )now[a[hd]]--,hd++; 42 } 43 if( ((now[0]<<1)==smm[n][0]) && 44 ((now[1]<<1)==smm[n][1]) && 45 ((now[2]<<1)==smm[n][2]) ){ 46 printf("2\n"); 47 return 0; 48 } 49 } 50 printf("3\n"); 51 return 0; 52 }
本文为博主原创文章,转载请注明出处。