题意

问题描述

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. C++编程模板2

    C++编程模板2 #include <iostream> using namespace std; /* */ int main(){ int ans; printf("%d\n ...

  2. Creating SSL Certificates for CRM Test Environment

    不必找第三方去申请证书了, Windows Server 自己也可以作为一个CA的. When working on a CRM Test environment there are many sce ...

  3. English trip -- VC(情景课)4 C My feet hurt 我脚痛

    xu言: You're the best... Grammar focus 语法点: eye  eyes hand hands foot feet tooth  teeth arm arms leg  ...

  4. codeforces 484a//Bits// Codeforces Round #276(Div. 1)

    题意:给出区间[ll,rr],求中间一个数二进制表示时一的个数最多. 写出ll和rr的二进制,设出现第一个不同的位置为pos(从高位到低位),找的数为x,那么为了使x在[ll,rr]内,前pos-1个 ...

  5. DB2性能调优

    1.更新统计信息 --更新数据库所有表统计信息 --连接到数据库(-v选项,表示要回显命令,以下同) db2 -v connect to DB_NAME --查看是否收集过统计信息,什么时候更新的   ...

  6. html form表单提交后处理返回数据

    上传如果通过form提交并且需要处理返回值.(其实用ajax上传方式刚好,看需要) 可以这么做: <form id="importBookForm" action=" ...

  7. 猎豹浏览器(chrome内核)屏蔽视频广告

    1.基于猎豹浏览器(原则上chrome内核浏览器都可以) 2.下载插件Adblock Plus,下载地址:http://chromecj.com/productivity/2014-07/24/dow ...

  8. CentOS 7 目录布局变化

    /bin转移到/usr/bin;/sbin转移到/usr/sbin;/lib转移到/usr/lib;/lib64转移到/usr/lib64. /var/run符号连接到/run;/var/lock符号 ...

  9. Beta 冲刺(7/7)

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10129067.html 作业博客:https://edu.cnblogs.com/campus ...

  10. 修改已经创建的docker容器的端口映射

    原始链接:https://stackoverflow.com/questions/19335444/how-do-i-assign-a-port-mapping-to-an-existing-dock ...