版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/88917302
题目:POJ1733.
题目大意:给定
个区间
和
,表示
的权值和为奇数或偶数,问到哪一个区间不矛盾,但它的下一个区间矛盾.
.
容易想到前缀和,那么区间就变成了两个点 和 上的信息.
考虑用带权并查集维护每个点的前缀和 ,一个点 的点权表示 的前缀和异或 的父亲的点权,即区间 的奇偶性.
加入一个区间 时若 在同一个区间就大力判断它们点权异或是否等于 .然后加入这个区间就相当于把 的祖先设为 ,并同时更新点权.
注意这个时候路径压缩时也要更新点权.
时间复杂度 .
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=5000;
int ri(){
char c=getchar();
int x=0,y=1;
for (;c<'0'||c>'9';c=getchar()) if (c=='-') y=-1;
for (;c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
return x*y;
}
int rc(){
char c=getchar();
while (c<'a'||c>'z') c=getchar();
return c=='o'?1:0;
}
int n,ord[N*2+9],x[N+9],y[N+9],a[N+9];
int fa[N*2+9],d[N*2+9],ans;
int lower(int k){
int l=1,r=n<<1,mid=l+r>>1;
for (;l<r;mid=l+r>>1)
k<=ord[mid]?r=mid:l=mid+1;
return l;
}
int get(int u){
if (u==fa[u]) return u;
int rot=get(fa[u]);d[u]^=d[fa[u]];
return fa[u]=rot;
}
Abigail into(){
ri();n=ri();
for (int i=1;i<=n;++i){
x[i]=ri()-1;y[i]=ri();a[i]=rc();
ord[i*2-1]=x[i];ord[i*2]=y[i];
}
}
Abigail work(){
sort(ord+1,ord+1+2*n);
for (int i=0;i<=n;++i)
x[i]=lower(x[i]),y[i]=lower(y[i]);
for (int i=1;i<=n<<1;++i) fa[i]=i;
int u,v;
ans=n;
for (int i=1;i<=n;++i){
u=get(x[i]);v=get(y[i]);
if (u==v&&d[x[i]]^d[y[i]]^a[i]){ans=i-1;return;}
fa[v]=u,d[v]=d[x[i]]^d[y[i]]^a[i];
}
}
Abigail outo(){
printf("%d\n",ans);
}
int main(){
into();
work();
outo();
return 0;
}