even
Posted cutepota
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了even相关的知识,希望对你有一定的参考价值。
第一行给你一个n(<=10^10)表示有一个长度为n的0,1字符串,
第二行给你一个m(<=5000)表示接下来有m行输入,
接下来的m行输入中
x, y, even表示第x到第y个字符中间1的个数为偶数个,
x, y, odd表示第x到第y个字符中间1的个数为奇数个,
若m句话中第k+1是第一次与前面的话矛盾, 输出k;否则输出m
Sample Input
10 //长度为10的字符串
5 //5个询问
1 2 even //区间1-2有偶数个1
3 4 odd //区间3-4有奇数个1
5 6 even
1 6 even
7 10 odd
Sample Output
3 //第4个询问与前3个询问矛盾
sol:本题用并查集开虚点的方法解决,类似犯罪团伙。
根据读入提取信息:某区间1的个数的奇偶性,用区间部分和表示。用sum[i]来表示前i个数的和,由于每一位是0、1数字,sum[i]为多少,表示前i位有多少个1。
若区间[i,j]1的个数为偶数,即sum[j]-sum[i-1]的值为偶数,则说明sum[j]与sum[i-1]的奇偶性一致,因为奇数-奇数得偶数,偶数-偶数得偶数,于是将i,j放在同一个集合。与i,j奇偶性相反的i’与j’应在同一集合。
若区间[i,j]1的个数为奇数,即sum[j]-sum[i-1]的值为奇数,则说明sum[j]与sum[i-1]的奇偶性相反,因为奇数-偶数得奇数,偶数-奇数得奇数,于是将i,j放在不同的集合。与i奇偶性相反的i’与j应在同一集合,与j奇偶性相反的j’与i应在同一集合。
另外,本题给出的n的值很大,是10^10,我们做并查集时要记录每一个结点的父亲结点,father数组需要开2*10^10那么大,超内存空间,而我们发现m的值不大,才5000内,就算每个区间的左右端点都不一样,也才10000个点,开虚点再翻倍,并且本题我们在做并查集连边时,只要知道左右端点的关系,是否在同一个集合中,跟两端点具体是什么值无关,因此我们可以做离散化的操作。将每个区间的左右端点映射成较小的数。
如有3个询问:[2..1000],[3..10^5],[9..10^9],可离散化为[1..4],[2..5],[3..6]
上面样例具体操作如下:
代码实现如下:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <stack> 7 #include <queue> 8 #include <vector> 9 #include <string> 10 #include <climits> 11 #include <iostream> 12 #define INF 0x3f3f3f3f 13 #define ll long long 14 #define dd double 15 using namespace std; 16 int dad[20100],m,n,a[20010],t; 17 char st[20100]; 18 struct node 19 { 20 int l,r,ty; 21 }que[10010]; 22 int getf(int x) 23 { 24 return x==dad[x]?x:dad[x]=getf(dad[x]); 25 } 26 int main() 27 { 28 scanf("%d",&m); 29 scanf("%d",&n); 30 for (int i=1;i<=n;i++) 31 { 32 scanf("%d%d%s",&que[i].l,&que[i].r,st); 33 que[i].ty=(st[0]==‘o‘?1:0);//如果是奇数就TRUE,偶数就FALSE 34 a[++t]=que[i].l-1,//记下左边界 35 a[++t]=que[i].r;//记下右边界 36 } 37 sort(a+1,a+t+1);//这个是做离散化用的 38 m=unique(a+1,a+t+1)-a-1;//算出a数组中有M种不同的数字 39 for (int i=1;i<=2*m;i++) //父亲点要开2倍 40 dad[i]=i; 41 for (int i=1;i<=n;i++)//n是询问数 42 { 43 int x=lower_bound(a+1,a+m+1,que[i].l-1)-a; 44 int y=lower_bound(a+1,a+m+1,que[i].r)-a; 45 int xx=x+m;//找出各自的对立点 46 int yy=y+m;//找出各自的对立点 47 if (que[i].ty==1) //如果这个记录是TRUE,则说x,y两个点的奇偶性是不一样的 48 { 49 if (getf(x)==getf(y)) //但是它们居然在同一个集合中,说明出错 50 { 51 printf("%d ",i-1); 52 return 0; 53 } 54 dad[getf(x)]=getf(yy);//如果前面没有退出,则将x与yy(y的对立面)放在一个集合中 55 dad[getf(xx)]=getf(y);//同上 56 } 57 else //说明这个记录是FALSE,则说x,y两个点的奇偶性是一样的 58 { 59 if (getf(x)==getf(yy)) //但是它们居然在同一个集合中,说明出错 60 { 61 printf("%d ",i-1); 62 return 0; 63 } 64 dad[getf(x)]=getf(y);//如果前面没有退出,则将x与y放在一个集合中 65 dad[getf(xx)]=getf(yy); 66 } 67 } 68 printf("%d ",n); 69 return 0; 70 }
以上是关于even的主要内容,如果未能解决你的问题,请参考以下文章
CSS 选择器 :nth-child(even) 与 jQuery( ":even" )