Parity game(poj1733)
有以个串,每次给出【i,j】之间的1的个数,
有m次询问,判断当前询问是否和之前的询问相冲突,冲突就break。
思路:
由于本题的区间范围有点大,所以要先离线。
- 本每次输入的左右区间依次存入一个 数组 中。
- 之后把重复的出现去掉unique(为了后面的二分查找)
- 之后就是带权并查集的基本操作,
- 本题的dis【】稍微改变一下,就可以了(本题even为0,odd为1)
- 所以find中的dis
dis[x]^=dis[f[x]];
- merge中的
f[A]=B;dis[A]=dis[x]^dis[y]^p[i].op;
反思
- 离线的学习。
For(i,1,q){int l,r;char s[10];scanf("%d%d%s", &l, &r, s);p[i].l=a[++cnt]=l-1;p[i].r=a[++cnt]=r;p[i].op=(s[0]=='o')?1:0;}
离线后之后直接访问第几个即可。
2. 异或运算的学习。
本题的操作和异或运算给很像
本题的路径并不是dis[A]=dis【b】- dis【a】+ x;
因为:
odd+odd=even;
odd-odd=even;
even+even=even;
even-even=even;
odd+even=odd;
odd-even=odd;
所以无关加减了,直接异或走起
AC
#include
#include
#include
#define For(i,x,y) for(register int i&#61;(x); i<&#61;(y); i&#43;&#43;)
using namespace std;
const int maxn&#61;1e4&#43;10;
struct point
{int l,r;int op;
}p[maxn];
int f[maxn<<1], dis[maxn<<1], a[maxn<<1],cnt,n,q,x;
int find(int x)
{if(x&#61;&#61;f[x])return x;int root&#61;find(f[x]);dis[x]^&#61;dis[f[x]];return f[x]&#61;root;
}
int main()
{scanf("%d", &n);scanf("%d", &q);For(i,1,q){int l,r;char s[10];scanf("%d%d%s", &l, &r, s);p[i].l&#61;a[&#43;&#43;cnt]&#61;l-1;p[i].r&#61;a[&#43;&#43;cnt]&#61;r;p[i].op&#61;(s[0]&#61;&#61;&#39;o&#39;)?1:0;}For(i,1,2*q)f[i]&#61;i;