Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2075 Accepted Submission(s): 615 Problem Description You are given a necklace consists of N beads linked as a circle. Each bead is either crystal or jade.
Input In the first line there is an integer T, indicates the number of test cases. (T<=50)
Output For each case, print “Case x: d” on a single line in which x is the number of case counted from one and d is the number of ways.
Sample Input 2 CJCJCJ CCJJCCJJCCJJCCJJ
Sample Output Case 1: 6 Case 2: 8
Author love8909
Source 2010 ACM-ICPC Multi-University Training Contest(4)——Host by UESTC
Recommend zhengfeng
|
题目大意:给个成环的字符串,现在要从一个地方断开这个环,然后可以向左或向右走,在走的过程中C的数量要始终保持大于J的数量,问共有多少个这样的端点
思路:我们以C为1J为-1,用cnt【i】表示前缀和,然后我们要找到的是前缀和不小于0的那一部分,这道题单调队列写两遍就行了,一次是全都向左走,另一次是全都向右走
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1000000+5;
struct queuey
{
int pos,sum;
}q[maxn*2];
int head,tail;
void insert(int pos,int sum)
{
while(head<tail&&sum<q[tail].sum)
tail--;
q[++tail].pos=pos;
q[tail].sum=sum;
}
char s[2*maxn],ss[2*maxn];
bool vis[2*maxn];
int cnt[2*maxn];
int main()
{
int kase=1,t;
scanf("%d",&t);
while(t--)
{
int count=0;
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++)
ss[i]=s[i];
for(int i=0;i<len;i++)
ss[len+i]=s[i];
cnt[0]=ss[0]=='C'?1:-1;
head=tail=0;
for(int i=1;i<2*len;i++)
cnt[i]=cnt[i-1]+(ss[i]=='C'?1:-1);
memset(vis,false,sizeof(vis));
for(int i=0;i<2*len;i++)
{
insert(i,cnt[i]);
while(q[head+1].pos<=i-len&&head<tail)
head++;
if(i-len>=0)
{
if(q[head+1].sum>=cnt[i-len])
if(vis[i]==0)
{
count++;
vis[i]=1;
}
}
}
head=tail=0;
cnt[2*len]=0;
cnt[2*len-1]=ss[2*len-1]=='C'?1:-1;
for(int i=2*len-2;i>=0;i--)
cnt[i]=cnt[i+1]+(ss[i]=='C'?1:-1);
for(int i=2*len;i>0;i--)
{
insert(i,cnt[i]);
while(q[head+1].pos>=i+len&&head<tail)
head++;
if(i<=len)
{
if(q[head+1].sum>=cnt[i+len])
if(vis[i+len-1]==0)
{
count++;
vis[i+len-1]=1;
}
}
}
printf("Case %d: %d\n",kase++,count);
}
}