ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【YbtOJ#20063】古老谜题

2020-10-12 17:04:56  阅读:260  来源: 互联网

标签:nxt cnt 20063 int YbtOJ sum 谜题 端点 区间


题目

题目链接:http://noip.ybtoj.com.cn/contest/90/problem/1
给定一个长度为 \(n\) 的 \(01\) 序列 \(a_1\sim a_n\)。
请你求出有多少个整数三元组 \((l,r,p)\),使得 \(1\leq l<p<r\leq n\) 并且 \(a_p=1\),且 \([l,p]\) 和 \([p,r]\) 中 \(1\) 的个数相同。

思路

显然题目要求的就是区间和为奇数并且中间的 \(1\) 不是区间端点的区间个数。
那么先求出有多少个区间和为 \(1\)。预处理出 \(sum\) 表示前缀异或和,以及 \(nxt[i]\) 表示 \(i\) 后面第一个 \(1\) 的位置。
枚举区间左端点,假设 \(sum[i]=1\),那么和为 \(1\) 的区间就是 \(sum\) 在 \(i\) 后面为 \(0\) 的数量。可以在右移左端点的同时计算。
然后减去中间的 \(1\) 在端点的情况,当 \(sum[i]=1\) 时,显然到下一个 \(1\) 之前所有区间都是不合法的,所以答案减去 \((nxt[i]-i)\);当 \(sum[i]=0\) 时,不合法区间只有 \([i,nxt[i]]\) 一个,答案减一。
时间复杂度 \(O(n)\)。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1000010;
int type,n,cnt[2],a[N],nxt[N],sum[N];
ll ans;

int main()
{
	freopen("puzzle.in","r",stdin);
	freopen("puzzle.out","w",stdout);
	scanf("%d%d",&type,&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%1d",&a[i]);
		sum[i]=sum[i-1]^a[i];
		cnt[sum[i]]++;
	}
	for (int i=n,last=n+1;i>=1;i--)
	{
		nxt[i]=last;
		if (a[i]==1) last=i;
	}
	for (int i=1;i<=n;i++)
	{
		if (i>1) cnt[sum[i-1]]--;
		ans+=cnt[sum[i-1]^1];
		if (!a[i] && nxt[i]<=n) ans--;
		if (a[i]) ans-=(nxt[i]-i);
	}
	printf("%lld",ans);
	return 0;
}

标签:nxt,cnt,20063,int,YbtOJ,sum,谜题,端点,区间
来源: https://www.cnblogs.com/stoorz/p/13803822.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有