古代龙人的谜题
(puzzle.cpp)
【问题描述】
Mark Douglas是一名调查员。他接受了「调查古代龙人」的任务。经过千辛万苦,Mark终于找到了一位古代龙人。Mark找到他时,他正在摆弄一些秘药,其中一些药丸由于是从很久以前流传下来的,发出了独特的光泽。古代龙人告诉了Mark一些他想知道的事情,看了看手中的秘药,决定考一考这位来访者。
古代龙人手中共有n粒秘药,我们可以用1表示「古老的秘药」,其余的用0表示。他将它们排成一列。古代龙人认为平衡是美的,于是他问Mark能选出多少个「平衡的区间」。「平衡的区间」是指首先选出一个区间[L, R],在它内部选出一个中间点mid(l<mid<r),满足mid是「古老的秘药」,且区间[L, mid]和[mid, R]中「古老的秘药」个数相等。
【输入格式】
输入文件名为puzzle.in。
第一行为一个正整数idx表示该测试点所属的子任务编号,子任务的详细信息请见「数据范围」。样例的子任务编号为0。
第二行为一个正整数n。
第三行为一个长度为n的字符串,仅包含0和1。
【输出格式】
输出文件名为puzzle.out。
输出仅一行表示答案。
【样例输入与输出】
example_puzzle1.in |
example_puzzle1.out |
0 7 1101011 |
7 |
更多样例请见example/puzzle/目录。
【数据范围】
本题采用捆绑测试,只有通过一个子任务中的全部测试点才能拿到这个子任务的分数。
对于所有子任务:。各子任务分值及特殊约束如下:
子任务1(8%):。
子任务2(26%):。
子任务3(24%):。
子任务4(5%):,字符串中仅有3个1。
子任务5(12%):字符串中全是1。
子任务6(25%)。
由于当我们确定了区间的两个端点以后,合法的中间点最多只有一个,且只要中间点存在(即区间[L, R]内有奇数个1)该区间就合法,所以我们枚举左端点L,同时维护在L右边且区间[1, R]内1的个数为奇数/偶数的点R的个数,答案就可以统计出来了。
code:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 long long a[1000006],s[1000005]; 5 int main(){ 6 long long num;cin>>num; 7 long long n;cin>>n; 8 string temp; 9 cin>>temp; 10 long long ans=0,c1=0,c2=0;//前缀和是奇数的个数,前缀和是偶数的个数 11 for(long long i=0;i<n;i++){ 12 a[i+1]=temp[i]-'0'; 13 s[i+1]=s[i]+a[i+1]; 14 if(a[i+1])ans--;//如果自己是一个1,减掉,因为不合法 15 } 16 for(long long i=1;i<=n;i++){ 17 if(s[i]&1)ans++;//如果前缀和是奇数,++ 18 if(s[i]&1)ans+=c2,c1++;//前缀和是奇数,减掉前面的奇数 19 else ans+=c1,c2++;//反之就是 20 } 21 long long cnt=0; 22 for(long long i=1;i<=n;i++){//0000001 23 if(a[i]==0)cnt++; 24 else ans-=cnt,cnt=0; 25 } 26 cnt=0; 27 for(long long i=n;i>0;i--){//1000000 28 if(a[i]==0)cnt++; 29 else ans-=cnt,cnt=0; 30 } 31 cout<<ans; 32 return 0; 33 }
over