题意:比较绕,n个表达式,表示a==b或者a!=b,有矛盾就重新开始,问可以分成多少段,每段多大。。
思路:倍增,On判断,也可以并查集加set维护(合并要注意使得集合头要是最早出现的。。),这里提供一下倍增的做法
PS。顺便吐槽一下百度之星的测评姬。。。还想吐槽一下自己比去年大概还弱,,今年怕是要打铁了
代码:
#include<bits/stdc++.h>
using namespace std;
#define MEM(a,b) memset(a,b,sizeof(a))
#define bug puts("bug");
#define PB push_back
#define MP make_pair
#define X first
#define Y second
typedef unsigned long long ll;
typedef pair<int,int> pii;
const int maxn=1e6+10;
using namespace std;
int n,a[maxn],b[maxn],c[maxn];
int f[maxn];
int fin(int x){
if(x==f[x]) return x;
return f[x]=fin(f[x]);
}
int un(int x,int y){
int fx=fin(x),fy=fin(y);
if(fx!=fy) f[fx]=fy;
}
int ok(int l,int r){
if(r>=n) return 0;
int ret=1;
for(int i=l;i<=r;i++) if(c[i]==1) un(a[i],b[i]);
for(int i=l;i<=r;i++) if(c[i]==0&&fin(a[i])==fin(b[i])) ret=0;
for(int i=l;i<=r;i++) f[a[i]]=a[i],f[b[i]]=b[i];
return ret;
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(int i=0;i<n+10;i++) f[i]=i;
int l=0;
vector<int> ans;
while(l<n){
int d=1;
int ll=l;
while(ok(l,ll+d)){
while(ok(l,ll+d*2)) d*=2;
ll+=d;
d=1;
}
if(ll+d<n)ans.PB(ll+d-l+1);
l=ll+d+1;
}
printf("%d
",ans.size());
for(int i=0;i<ans.size();i++)
printf("%d
",ans[i]);
}
return 0;
}