10.11T1 预处理+去掉不合法答案

古代龙人的谜题

(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

原文地址:https://www.cnblogs.com/saionjisekai/p/9774819.html