题意

问题描述

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. [.NET开发] 浅说C#异步和同步

    提到异步,那么与之对应的是什么呢?同步.那么C#的异步和同步是如何工作的呢? 首先,我们先来看看栗子: 新建一个控制台应用程序,在Program文件中添加如下代码: 1 static void Mai ...

  2. Symbol的控件模板

    <esriSymbols:TextSymbol x:Name="text1" Text="adadfdf"></esriSymbols:Tex ...

  3. WPF中的动画

    动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互.这里我们讨论一下故事板. 在WPF中我们采用Storyboard(故事板)的方式来编写动画,为了对St ...

  4. LeetCode--108--将有序数组转化为二叉搜索树

    问题描述: 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10 ...

  5. 使用nginx+dnsmasq解决同IP不同端口Session冲突问题

    由于一台服务器上需要部署多个项目,而我们的WEB项目因为用到框架都是一样的,导致同时运行,session相互冲突,这个登录后,那个就得重新登录,造成了使用不方便,原因是IP相同认为是同一个域,接收了B ...

  6. POJ-3087 Shuffle'm Up (模拟)

    Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuff ...

  7. UVA-11490 Just Another Problem

    题目大意:一个由p*q个点组成的pxq点阵(构成一个矩形).从内层点中拿走两块正方形上的所有点,这两块正方形要边长相等,在位置上关于中线对称,并且还要使每一个正方形的上下左右剩余的点的层数相等.现在告 ...

  8. OAF 清空指定控件或区域的值

    CO if (pageContext.getParameter("ClearBtn") != null) { clearRegion(pageContext, webBean, & ...

  9. 1.strcpy使用注意

    void test1() { char string[10]; char *str1 ="0123456789"; strcpy(string,str1); } 上述代码问题? 字 ...

  10. POJ 3308 Paratroopers 最大流,乘积化和 难度:2

    Paratroopers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7267   Accepted: 2194 Desc ...