这道题我用的并查集做的。
首先对数据做离散化。
按给出的顺序依次处理每次问答。
并查集每个节点维护三个值:
root:该点的根节点(从根节点到该节点的整个区间的奇偶性已经确定);
sign:该节点是否是某个奇偶性确定区间的右端点;
eo:该集合的根节点到该点的区间的奇偶性;
结束:在遇到某区间的奇偶性出现矛盾时结束(后来得到的奇偶性和之前确定的奇偶性不同)。
每次先找到a-1和b的根节点;
如果a-1没有根节点:
『
如果b没有根节点:b的root设为a,更新b的sign,eo;
如果b的根节点就是a,考察a到b区间是否出现矛盾;
否则得到两个区间[fb,a-1]和[a,b],或[a,fb-1]和[fb,b],这两个区间的奇偶性都可得到,
更新其奇偶性。
』
如果a-1的根节点为fa:
『
如果b没有根节点,b的根基点设为a,更新b的sign和eo;
如果fa==fb,做奇偶性判断;
否则,会从区间的并分解得到两个或三个互不相交的区间,这些区间的奇偶性可以得到。
』
#include<cstdio> #include<cstring> #include<cstdlib> #include<string> #include<cmath> #include<iostream> #include<algorithm> using namespace std; #define PN printf("\n"); char chrn; #define SCRN while(scanf("%c",&chrn) && chrn!='\n'); typedef struct { int a,b,id,eo; }node1; typedef struct { int n,id,type; }node2; typedef struct { int root,sign,eo; }node3; int n,last; node1 a[5001]; node2 b[10001]; node3 set[10001]; bool cmp(node2 a,node2 b) { if(a.n<b.n) return true; return false; } void discrete(int t) { int i,num,m; sort(b,b+t,cmp); num=0; m=b[0].n; for(i=0; i<t; i++) { if(b[i].n>m) { m=b[i].n; num++; } if(b[i].type==1) a[b[i].id].a=num; else a[b[i].id].b=num; } } void ini_set() { int i; for(i=0; i<=10000; i++) set[i].sign = 0; } int findroot(int k) { int root; if(k<0 || set[k].sign == 0) return -1; root = findroot(set[k].root-1); if(root == -1) return set[k].root; else { set[k].eo ^= set[set[k].root-1].eo; return set[k].root = root; } } void D() { int i,fa,fb,eo; node1 nd; last=0; ini_set(); for(i=0; i<n; i++) { last++; nd = a[i]; fa = findroot(nd.a-1); fb = findroot(nd.b); if(fa == -1) { if(fb == -1) { set[nd.b].sign = 1; set[nd.b].root = nd.a; set[nd.b].eo = nd.eo; } else if(fb == nd.a) { if(set[nd.b].eo != nd.eo){ //printf("OP2:"); return; } } else if(fb < nd.a) { set[nd.a-1].sign = 1; set[nd.a-1].root = fb; set[nd.a-1].eo = set[nd.b].eo ^ nd.eo; } else if(fb > nd.a) { set[fb-1].sign = 1; set[fb-1].root = nd.a; set[fb-1].eo = set[nd.b].eo ^ nd.eo; set[nd.b].root = nd.a; set[nd.b].eo = nd.eo; } } else { if(fb == -1) { set[nd.b].sign = 1; set[nd.b].root = fa; set[nd.b].eo = set[nd.a-1].eo ^ nd.eo; } else if(fa == fb) { if((set[nd.b].eo ^ set[nd.a-1].eo) !=nd.eo) { //printf("OP1:"); return; } } else if(fb<fa) { set[fa-1].sign = 1; set[fa-1].root = fb; set[fa-1].eo = set[nd.a-1].eo ^ set[nd.b].eo ^ nd.eo; } else if(fb>fa && fb<nd.a) { set[fb-1].sign = 1; set[fb-1].root = fa; set[fb-1].eo = set[nd.a-1].eo ^ set[nd.b].eo ^ nd.eo; } else if(fb>nd.a) { set[fb-1].sign = 1; set[fb-1].root = nd.a; set[fb-1].eo = set[nd.b].eo ^ nd.eo; findroot(nd.b); } } } last++; } int main() { int m,i,j; char s[5]; while(scanf("%d",&m)!=EOF) { scanf("%d",&n); for(i=0,j=0; i<n; i++) { scanf("%d %d %s",&a[i].a,&a[i].b,s); if(s[0]=='e') a[i].eo=0; else a[i].eo=1; a[i].id=i+1; b[j].n=a[i].a; b[j].type=1; b[j++].id=i; b[j].n=a[i].b; b[j].type=2; b[j++].id=i; } discrete(2*n); D(); printf("%d\n",last-1); } return 0; }