题意

问题描述

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。

输出仅一行表示答案。

样例输入

0

7

1101011

样例输出

7

数据范围

本题采用捆绑测试,只有通过一个子任务中的全部测试点才能拿到这个子任务的分数。

对于所有子任务:1≤n≤〖10〗^6。各子任务分值及特殊约束如下:

子任务1(8%):1≤n≤50。

子任务2(26%):1≤n≤300。

子任务3(24%):1≤n≤2000。

子任务4(5%):n≥3,字符串中仅有3个1。

子任务5(12%):字符串中全是1。

子任务6(25%)。

分析

考场做法

考虑分别计算以i为结尾,起始在[1,i-1]内的合法区间个数。

按串的0/1分为两种情况。

  1. 此位是0。先算前面0的贡献,考虑维护一个cnt[2]数组,令每遇到一个1就让cur异或1,统计0的个数,相当于按1划分0的段,显然此位的答案应加上cnt[cur^1]。然后算1的贡献,应该是此位之前1的中,距它中间间隔了正偶数个1的1的个数。
  2. 此位是1。先算前面0的贡献,应该是与此1同段的,且是非相邻0段的0的个数。所以要维护一个last数组,代表此位之前最近的1的位置。然后算1的贡献,应该是此位之前的1中,距它中间间隔了正奇数个1的1的个数。

代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff; const int MAXN=1e6+7; int n;
char s[MAXN]; int last[MAXN];
int pre[MAXN];
int cnt[2],cur=0;
int f[MAXN];
/*
0
5
10010
*/
int main()
{
freopen("puzzle.in","r",stdin);
freopen("puzzle.out","w",stdout);
int id;
read(id);
read(n);
scanf("%s",s+1);
ll ans=0;
for(int i=1;i<=n;++i)
{
pre[i]=pre[i-1]+(s[i]=='1');
if(s[i]=='0')
{
f[i]=cnt[cur^1]+(pre[i]-1)/2;
++cnt[cur];
last[i+1]=last[i];
}
else if(s[i]=='1')
{
f[i]=pre[i-1]/2+cnt[cur]-(i-last[i]-1);
// cerr<<" cnt="<<cnt[cur]<<" judge="<<judge(i)<<endl;
cur^=1;
last[i+1]=i;
}
// cerr<<i<<" f="<<f[i]<<endl;
// cerr<<" cur="<<cur<<" cnt="<<cnt[cur]<<endl;
ans+=f[i];
}
printf("%lld\n",ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}

题解

由于当我们确定了区间的两个端点以后,合法的中间点最多只有一个,且只要中间点存在(即区间[L, R]内有奇数个1)该区间就合法,所以我们枚举左端点L,同时维护在L右边且区间[1, R]内1的个数为奇数/偶数的点R的个数,答案就可以统计出来了。

std

#include <cstdio>

using LL = long long;

const int MAXN = 1e6 + 5;

int n, seq[MAXN];
int cnt, right[MAXN];
LL sum[2]; int main() {
#ifndef LOCAL
freopen("puzzle.in", "r", stdin);
freopen("puzzle.out", "w", stdout);
#endif scanf("%*d%d", &n); cnt = 0;
for (int i = 1; i <= n; ++i) {
scanf("%1d", seq + i);
cnt += seq[i];
} int tmp = 0;
for (int i = n, j = cnt; i; --i) {
++tmp;
if (seq[i] == 1) {
right[j--] = tmp; tmp = 0;
}
}
sum[0] = sum[1] = 0;
for (int i = 1; i <= cnt; i += 2) sum[1] += right[i];
for (int i = 2; i <= cnt; i += 2) sum[0] += right[i]; LL ans = 0; tmp = 0;
for (int i = 1, j = 1; i <= n; ++i) {
++tmp;
if (seq[i] == 1) {
ans += (tmp - 1ll) * (right[j] - 1ll) + tmp * (sum[j & 1] - right[j]);
sum[j & 1] -= right[j];
++j; tmp = 0;
}
} printf("%lld\n", ans); return 0;
}

test20180922 古代龙人的谜题的更多相关文章

  1. NOIp2018集训test-9-22(am/pm) (联考三day1/day2)

    szzq学长出的题,先orz一下. day1 倾斜的线 做过差不多的题,写在我自己的博客里,我却忘得一干二净,反而李巨记得清清楚楚我写了的. 题目就是要最小化这个东西 $|\frac{y_i-y_j} ...

  2. SQL 谜题(硬币的组合)

    问题:早在ITPUB中看过有个SQL高手,喜欢出谜题,以下是一个谜题.我试用SQL SERVER解决此问题. 用1分,5分,10分,25分,50分硬币凑成一元,总共有几种组合办法? SELECT'1* ...

  3. [变]C#谜题(1-10)表达式篇

    [变]C#谜题(1-10)表达式篇 最近偶然发现了<Java谜题>,很有意思,于是转到C#上研究一下. 本篇是关于表达式的一些内容. 谜题1:奇数性(负数的取模运算) 下面的方法意图确定它 ...

  4. BZOJ1951[SDOI2010]古代猪文

    Description "在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心--" --选自猪王国民歌 很久 ...

  5. UOJ260 【NOIP2016】玩具谜题

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  6. 【BZOJ1951】【SDOI2010】古代猪文 Lucas定理、中国剩余定理、exgcd、费马小定理

    Description “在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心……” ——选自猪王国民歌 很久很久以前,在山的那边 ...

  7. 发布HTML5 RTS游戏-古代战争

    古代战争 游戏介绍 "古代战争"是一个2.5D即时战略游戏,使用了帝国时代2的素材,并参考了它的游戏设计和玩法. 游戏基于YEngine2D引擎开发,具备生产.建造.资源采集.战斗 ...

  8. BZOJ-1951 古代猪文 (组合数取模Lucas+中国剩余定理+拓展欧几里得+快速幂)

    数论神题了吧算是 1951: [Sdoi2010]古代猪文 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 1573 Solved: 650 [Submit ...

  9. 几个Unicode新知识:扩展ANSI有很多种(256个字符),Unicode表示ANSI字符时高字节为0,Unicode不包括古代字符

    都是有些模糊的概念,特别是Unicode不包括古代字符让我有点惊讶.看来Unicode只适用于大多数情况,一旦有无法表示的字符,那该怎么办呢? ANSI针对英语设计的,当处理带有音调标号(形如汉语的拼 ...

随机推荐

  1. h1042 N!大数乘int

    计算10000以内某个数的阶乘,即大数乘以int,考虑到一个int存一个数位过于繁琐且浪费空间,采用万进制 一个int存四个位数,但注意除了最高位,其他位不够四位数时要加上前导0凑够四位: 例1234 ...

  2. Hibernate---运行原理

    Hibernate---运行原理

  3. OC 类对象和类加载

    //------------------------Persion类----------------------------// 1 #import "Person.h" @imp ...

  4. 小程序中的bindtap和catchtap的区别(交流QQ群:604788754)

    bindtap绑定的节点,如果他的父节点也有绑定事件,点击之后就会出现冒泡. catchtap绑定的节点,如果他的父节点也有绑定事件,点击之后不会出现冒泡.

  5. jsp jsp运行原理

    JSP的运行原理  每个jsp页面在第一次被访问时,WEB容器都会把请求交给jsp引擎(一个java程序).Jsp 引擎先将jsp翻译成一个_jspServlet实质上也是一个servlet,然后按照 ...

  6. httpclient 多线程请求

    线程请求执行 当配备一个线程池管理器后,如PollingClientConnectionManager,HttpClient就能使用执行着的多线程去执行并行的多请求. PollingClientCon ...

  7. hadoop kafka install (6)

    reference: http://kafka.apache.org/quickstart  http://dblab.xmu.edu.cn/blog/1096-2/ hadoop@iZuf68496 ...

  8. Hibernate基于【XML】和【注解】——完整实例

    Eclipse中新建Java Project工程: 工程结构  和  需要的Jar包: 我用的SqlServer数据库,所以连接数据库的Jar包是sqljdbc4.jar 一.基于XML配置 1.实体 ...

  9. Apache自带性能测试工具ab的使用

    Apache服务器套件自带ab,只要安装Apache即可,无需另行安装ab.ab位于%ApacheHome%/bin目录下(“%ApacheHome%”为Aapche安装路径),你也可以把ab.exe ...

  10. Java——IO类,字节流读数据

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...