线段树
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 100000
#define ll long long
ll tree[maxn<<2];
ll num[maxn];
char c[10];
int n;
void update(int now){
tree[now]=tree[now<<1]+tree[now<<1|1];
}
void build(int l, int r, int now){
if(l==r){
tree[now]=num[l];
return ;
}
int mid=(l+r)/2;
build(l, mid, now<<1);
build(mid+1, r, now<<1|1);
update(now);
}
void change(int l, int r, int now, int x, ll c){
if(l==r){
tree[now]+=c;
return;
}
int mid=(l+r)/2;
if(x<=mid) change(l, mid, now<<1, x, c);
else change(mid+1, r, now<<1|1, x, c);
update(now);
}
ll seartch(int l, int r, int now, int i, int j){
if(i<=l&&r<=j) return tree[now];
ll ans=0;
int mid=(l+r)/2;
if(i<=mid) ans+=seartch(l, mid, now<<1, i, j);
if(j>mid) ans+=seartch(mid+1, r, now<<1|1, i, j);
return ans;
}
int main(){
int T;
scanf("%d", &T);
for(int s=1;s<=T;s++){
printf("Case %d:\n", s);
scanf("%d", &n);
for(int i=1;i<=n;i++){
scanf("%lld", &num[i]);
}
build(1, n, 1);
ll a, b;
while(~scanf("%s", c)){
if(c[0]=='E') break;
scanf("%lld %lld", &a, &b);
if(c[0]=='A') change(1, n, 1, (int)a, b);
if(c[0]=='S') change(1, n, 1, (int)a, -b);
if(c[0]=='Q') printf("%lld\n", seartch(1, n, 1, (int)a, (int)b));
}
}
return 0;
}
线段树+lazy
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 500000
#define ll long long
ll tree[maxn<<2];
ll lazy[maxn<<2];
int n,m;
void update(int now){
tree[now]=tree[now<<1]+tree[now<<1|1];
}
void update_lazy(int now,int d){
if(lazy[now]!=0){
tree[now<<1]=lazy[now]*(d-d/2);
tree[now<<1|1]=lazy[now]*(d/2);
lazy[now<<1]=lazy[now];
lazy[now<<1|1]=lazy[now];
lazy[now]=0;
}
}
void build(int l, int r, int now){
if(l==r){
tree[now]=1;
return ;
}
int mid=(l+r)/2;
build(l, mid, now<<1);
build(mid+1, r, now<<1|1);
update(now);
}
void change_lazy(int l, int r, int now, int i, int j, ll c){
if(i<=l&&r<=j){
tree[now]=c*(r-l+1);
lazy[now]=c;
return;
}
update_lazy(now,(r-l+1));
int mid=(l+r)/2;
if(i<=mid) change_lazy(l, mid, now<<1, i, j, c);
if(j>mid) change_lazy(mid+1, r, now<<1|1, i, j, c);
update(now);
}
ll seartch(int l, int r, int now, int i, int j){
if(i<=l&&r<=j) return tree[now];
update_lazy(now,r-l+1);
ll ans=0;
int mid=(l+r)/2;
if(i<=mid) ans+=seartch(l, mid, now<<1, i, j);
if(j>mid) ans+=seartch(mid+1, r, now<<1|1, i, j);
return ans;
}
int main(){
int T,t=1;
scanf("%d", &T);
while(T--){
memset(tree,0,sizeof tree);
memset(lazy,0,sizeof lazy);
scanf("%d %d", &n, &m);
build(1, n, 1);
ll a, b, d;
while(m--){
scanf("%lld %lld %lld", &a, &b, &d);
change_lazy(1, n, 1, (int)a, (int)b, d);
}
printf("Case %d: The total value of the hook is %lld.\n", t++, seartch(1, n, 1, 1, n));
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define maxn 510000
struct node{
int lazy;
int num;
}tree[maxn];
void update(int now,int d){
if(tree[now].lazy!=0){
tree[now<<1].num=tree[now].lazy*(d-d/2);
tree[now<<1|1].num=tree[now].lazy*(d/2);
tree[now<<1].lazy=tree[now].lazy;
tree[now<<1|1].lazy=tree[now].lazy;
tree[now].lazy=0;
}
}
void build(int now,int l,int r){
tree[now].lazy=0;
if(l==r){
tree[now].num=1;
return ;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
tree[now].num=tree[now<<1].num+tree[now<<1|1].num;
}
void change(int now,int l,int r,int i,int j,int c){
if(i<=l&&r<=j){
tree[now].num=c*(r-l+1);
tree[now].lazy=c;
return ;
}
update(now,r-l+1);
int mid=(l+r)>>1;
if(i<=mid) change(now<<1,l,mid,i,j,c);
if(j>mid) change(now<<1|1,mid+1,r,i,j,c);
tree[now].num=tree[now<<1].num+tree[now<<1|1].num;
}
int seartch(int now,int l,int r,int i,int j){
if(i<=l&&r<=j){
return tree[now].num;
}
int ans=0;
update(now,r-1+1);
int mid=(l+r)>>1;
if(i<=mid) ans+=seartch(now<<1,l,mid,i,j);
if(j>mid) ans+=seartch(now<<1|1,mid+1,r,i,j);
return ans;
}
int main(){
int T,t=1;
int l,r,k;
int n,m;
scanf("%d", &T);
while(T--){
scanf("%d %d", &n, &m);
build(1,1,n);
while(m--){
scanf("%d %d %d", &l, &r, &k);
change(1,1,n,l,r,k);
}
printf("Case %d: The total value of the hook is %d.\n", t++, seartch(1,1,n,1,n));
}
return 0;
}
线段树+离散化
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 100000
struct node {
int l;
int r;
} num[maxn];
int tree[maxn<<2];
int color[maxn<<1];
int has[10000010];
bool vis[maxn<<1];
int cnt;
void init(){
memset(tree, 0, sizeof tree);
memset(vis, false, sizeof vis);
cnt = 0;
}
void updown(int now){
if(tree[now] != -1){
tree[now << 1] = tree[now << 1 | 1] = tree[now];
tree[now] = -1;
}
}
void change(int l, int r, int now, int i, int j, int c){
if(i <= l && r <= j){
tree[now] = c;
return ;
}
updown(now);
int mid = (l + r) / 2;
if(i <= mid) change(l, mid, now<<1, i, j, c);
if(j > mid) change(mid+1, r, now<<1|1, i, j, c);
}
void seartch(int l, int r, int now, int i, int j){
if(tree[now] != -1){
vis[tree[now]] = true;
return;
}
int mid = (l + r) / 2;
if(i <= mid) seartch(l, mid, now<<1, i, j);
if(j > mid) seartch(mid+1, r, now<<1|1, i, j);
}
int main() {
int T, n;
scanf("%d", &T);
while(T--){
init();
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d %d", &num[i].l, &num[i].r);
color[cnt++] = num[i].l;
color[cnt++] = num[i].r;
}
sort(color, color + cnt);
cnt = unique(color, color + cnt) - color;
for(int i = 1; i <= cnt; i++) {
has[color[i - 1]] = i;
}
for(int i = 1; i <= n; i++) {
change(1, cnt, 1, has[num[i - 1].l], has[num[i - 1].r], i);
}
seartch(1, cnt, 1, 1, cnt);
int ans = 0;
for(int i = 1; i <= n; i++) {
if(vis[i]){
ans++;
}
}
printf("%d\n", ans);
}
return 0;
}
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 100000
using namespace std;
struct TREE{
int l,r;
bool v;
}tree[maxn<<2];
struct node{
int l,r;
}num[maxn];
int Hash[10000010];
int color[maxn<<1];
int n;
void build(int l,int r,int now){
tree[now].l=l;
tree[now].r=r;
tree[now].v=false;
if(l==r) return ;
int mid=(l+r)>>1;
build(l,mid,now<<1);
build(mid+1,r,now<<1|1);
}
bool update(int l,int r,int now){
if(tree[now].v) return false;
if(tree[now].l==l&&tree[now].r==r){
tree[now].v=true;
return true;
}
int temp;
int mid=(tree[now].l+tree[now].r)>>1;
if(r<=mid) temp=update(l,r,now<<1);
else if(l>mid) temp=update(l,r,now<<1|1);
else{
bool t1=update(l,mid,now<<1);
bool t2=update(mid+1,r,now<<1|1);
temp=t1||t2;
}
tree[now].v=tree[now<<1].v&&tree[now<<1|1].v;
return temp;
}
void init(){
int cnt=0;
scanf("%d", &n);
for(int i=0;i<n;i++){
scanf("%d %d", &num[i].l, &num[i].r);
color[cnt++]=num[i].l;
color[cnt++]=num[i].r;
}
sort(color, color+cnt);
cnt=unique(color,color+cnt)-color;
build(1,cnt,1);
int ans=0;
for(int i=n-1;i>=0;i--){
int l=num[i].l, r=num[i].r;
if(update(Hash[l], Hash[r], 1)) ans++;
}
printf("%d\n", ans);
}
int main(){
int T;
scanf("%d", &T);
while(T--){
init();
}
return 0;
}
可持久化线段树
#include <bits/stdc++.h>
using namespace std;
#define maxn 1000005
int n,m,tot;
int a[maxn],root[maxn];
struct node{
int l,r,v;
}tree[maxn<<5];
void up(int now){
tree[now].v=tree[tree[now].l].v+tree[tree[now].r].v;
}
int build_tree(int l,int r){
int pos=++tot;
if(l==r){
tree[pos].v=a[l];
return pos;
}
int mid=l+(r-l)/2;
tree[pos].l=build_tree(l,mid);
tree[pos].r=build_tree(mid+1,r);
up(pos);
return pos;
}
int update(int now,int l,int r,int tar,int v){
int pos=++tot;
if(l==r){
tree[pos].v=v;
return pos;
}
int mid=l+(r-l)/2;
tree[pos].l=tree[now].l;
tree[pos].r=tree[now].r;
up(pos);
if(tar<=mid) tree[pos].l=update(tree[now].l,l,mid,tar,v);
else tree[pos].r=update(tree[now].r,mid+1,r,tar,v);
return pos;
}
int query(int now,int l,int r,int q){
if(l==r){
return now;
}
int mid=l+(r-l)/2;
if(q<=mid) return query(tree[now].l,l,mid,q);
else return query(tree[now].r,mid+1,r,q);
}
int main(){
int n,m;
while(~scanf("%d %d", &n, &m)){
tot=0;
for(int i=1;i<=n;i++){
scanf("%d", &a[i]);
}
root[0]=build_tree(1,n);
int u,v,l,k;
for(int i=1;i<=m;i++){
scanf("%d %d %d", &u, &k, &l);
if(k==1){
scanf("%d", &v);
root[i]=update(root[u],1,n,l,v);
}else{
printf("%d\n", tree[query(root[u],1,n,l)].v);
root[i]=root[u];
}
}
}
return 0;
}
主席树
#include <bits/stdc++.h>
using namespace std;
#define maxn 200010
int n,m,tot;
int a[maxn],b[maxn],root[maxn];
struct node{
int l,r,v;
}tree[maxn<<5];
int build_tree(int l,int r){
int pos=++tot;
tree[pos].v=0;
if(l==r){
return pos;
}
int mid=l+(r-l)/2;
tree[pos].l=build_tree(l,mid);
tree[pos].r=build_tree(mid+1,r);
return pos;
}
int update(int now,int tar,int l,int r){
int pos=++tot;
if(l==r){
tree[pos].v=tree[now].v+1;
return pos;
}
int mid=l+(r-l)/2;
tree[pos].l=tree[now].l;
tree[pos].r=tree[now].r;
if(tar<=mid) tree[pos].l=update(tree[now].l,tar,l,mid);
else tree[pos].r=update(tree[now].r,tar,mid+1,r);
tree[pos].v=tree[tree[pos].l].v+tree[tree[pos].r].v;
return pos;
}
int query(int now,int last,int k,int l,int r){
if(l==r){
return l;
}
int mid=l+(r-l)/2;
int cnt=tree[tree[now].l].v-tree[tree[last].l].v;
if(k<=cnt) return query(tree[now].l,tree[last].l,k,l,mid);
else return query(tree[now].r,tree[last].r,k-cnt,mid+1,r);
}
int main(){
int n,m;
while(~scanf("%d %d", &n, &m)){
tot=0;
for(int i=1;i<=n;i++){
scanf("%d", &a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
int res=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+1+res,a[i])-b;
}
root[0]=build_tree(1,res);
for(int i=1;i<=n;i++){
root[i]=update(root[i-1],a[i],1,res);
}
int l,r,k;
while(m--){
scanf("%d %d %d", &l, &r, &k);
printf("%d\n", b[query(root[r],root[l-1],k,1,res)]);
}
}
return 0;
}
树状数组
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxn 500010
int n;
int a[maxn];
int t[maxn*4];
struct node{
int x;
int id;
}f[maxn];
bool cmp(node a, node b){
return a.x<b.x;
}
void update(int x,int val){
while(x<=n){
t[x]+=val;
x+=x&(-x);
}
}
int sum(int x){
int ans=0;
while(x>=1){
ans+=t[x];
x-=x&(-x);
}
return ans;
}
int main(){
while(~scanf("%d", &n),n){
for(int i=1;i<=n;i++){
scanf("%d", &f[i].x);
f[i].id=i;
}
sort(f+1,f+n+1,cmp);
for(int i=1;i<=n;i++) a[i]=f[i].id;
memset(t,0,sizeof(t));
long long ans=0;
for(int i=1;i<=n;i++){
update(a[i],1);
ans+=(i-sum(a[i]));
}
printf("%lld\n", ans);
}
return 0;
}
树状数组维护差分数组
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 1000000
ll a[maxn];
ll tree[maxn<<1];
ll n,m;
inline long long read()
{
long long x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-48;c=getchar();}
return x*f;
}
void update(int x,int val){
while(x<=n){
tree[x]+=val;
x+=x&(-x);
}
}
long long sum(long long x){
long long ans=0;
while(x>=1){
ans+=tree[x];
x-=x&(-x);
}
return ans;
}
int main(){
int s,l,r,x;
n=read();
m=read();
memset(tree,0,(n+1)*sizeof (ll));
for(int i=1;i<=n;i++){
a[i]=read();
update(i,a[i]-a[i-1]);
}
while(m--){
s=read();
if(s==2){
x=read();
printf("%lld\n", sum(x));
}else{
l=read();
r=read();
x=read();
update(l,x);
update(r+1,-x);
}
}
}
扫描线
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 5010
struct node{
int ss;
double l,r,h;
node(double l1=0,double r1=0,double h1=0,int ss1=0){
l=l1;
r=r1;
h=h1;
ss=ss1;
}
}edge[maxn<<2];
int add[maxn];
double x[maxn<<2],sum[maxn<<2];
bool cmp(node a,node b){
return a.h<b.h;
}
void pushup(int now,int l,int r){
if(add[now]) sum[now]=x[r+1]-x[l];
else if(l==r) sum[now]=0;
else sum[now]=sum[now<<1]+sum[now<<1|1];
}
void update(int now,int L,int R,int val,int l,int r){
if(L<=l&&r<=R){
add[now]+=val;
pushup(now,l,r);
return ;
}
int mid=(l+r)>>1;
if(L<=mid) update(now<<1,L,R,val,l,mid);
if(R>mid) update(now<<1|1,L,R,val,mid+1,r);
pushup(now,l,r);
}
int main(){
int n;
double x1,x2,y1,y2,ans;
while(cin>>n && n){
ans=0;
int top=0,l,r;
for(int i=0;i<n;i++){
cin>>x1>>y1>>x2>>y2;
x[top]=x1;
edge[top++]=node(x1,x2,y1,1);
x[top]=x2;
edge[top++]=node(x1,x2,y2,-1);
}
sort(x,x+top);
sort(edge,edge+top,cmp);
int k = 1;
for(int i=1; i<top; i++)
{
if(x[i] != x[i-1])
x[k++] = x[i];
}
memset(add,0,sizeof(add));
memset(sum,0,sizeof(sum));
for(int i=0; i<top-1; i++){
l=lower_bound(x,x+k,edge[i].l)-x;
r=lower_bound(x,x+k,edge[i].r)-x-1;
update(1,l,r,edge[i].ss,0,k-1);
ans+=(sum[1]*(edge[i+1].h-edge[i].h));
}
cout<<(int)ans<<endl;
}
cout<<"*"<<endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define maxn 1000100
#define ll long long
int n,m,p,cnt;
int tree[maxn];
int sum[maxn],res[maxn];
struct node{
int f,L,R,h,id;
int val;
}edge[maxn];
int get(int x, int y){
long long centre = (long long)n*n;
long long cen = n/2+1;
long long val;
if (x==cen && y==cen){
int ans=0;
val=centre;
while(val){
ans+=val%10;
val=val/10;
}
return ans;
}
long long Max = max(abs(x-cen), abs(y-cen));
val = centre - Max * (4*Max +1);
if((y == (cen-Max) && x >= cen) || x == cen + Max) val -= (x-cen) + (y-cen+Max);
else {
if(y != (cen-Max)) val += (x-cen + Max) + (y-cen + Max) + Max;
else val += cen - x;
}
int ans=0;
while(val){
ans+=val%10;
val=val/10;
}
return ans;
}
bool cmp(node a,node b){
if(a.h==b.h){
if((a.f==1&&b.f==0)||(b.f==1&&a.f==0)) return a.f>b.f;
else return a.f<b.f;
}
return a.h<b.h;
}
void update(int pow,int val){
while(pow<maxn){
tree[pow]+=val;
pow+=(-pow)&pow;
}
}
int query(int pow){
int ans=0;
while(pow>0){
ans+=tree[pow];
pow-=(-pow)&pow;
}
return ans;
}
int main(){
int T;
int x1,x2,y1,y2,x,y;
cin>>T;
while(T--){
scanf("%d %d %d", &n, &m, &p);
cnt=0;
memset(tree,0,sizeof tree);
while(m--){
scanf("%d %d", &x, &y);
edge[cnt++]=(node){0,x,0,y,0,get(x,y)};
}
for(int i=1;i<=p;i++){
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
edge[cnt++]=(node){1,x1,x2,y1,i,0};
edge[cnt++]=(node){2,x1,x2,y2,i,0};
}
sort(edge,edge+cnt,cmp);
for(int i=0;i<cnt;i++){
if(edge[i].f==0) update(edge[i].L,edge[i].val);
else if(edge[i].f==1) sum[edge[i].id]=query(edge[i].R)-query(edge[i].L-1);
else res[edge[i].id]=query(edge[i].R)-query(edge[i].L-1)-sum[edge[i].id];
}
for(int i=1;i<=p;i++){
printf("%d\n", res[i]);
}
}
return 0;
}
01字典树
#include <bits/stdc++.h>
using namespace std;
#define maxn 100000
#define ll long long
int tol;
ll val[32*maxn];
int ch[32*maxn][2];
void init(){
tol=1;
ch[0][0]=ch[0][1]=0;
}
void insert(ll x){
int u=0;
for(int i=32;i>=0;i--){
int v=(x>>i)&1;
if(!ch[u][v]){
ch[tol][0]=ch[tol][1]=0;
val[tol]=0;
ch[u][v]=tol++;
}
u=ch[u][v];
}
val[u]=x;
}
ll query(ll x){
int u=0;
for(int i=32;i>=0;i--){
int v=(x>>i)&1;
if(ch[u][v^1]) u=ch[u][v^1];
else u=ch[u][v];
}
return val[u];
}
int main(){
int T,n,m;
ll a;
scanf("%d",&T);
for(int s=1;s<=T;s++){
init();
scanf("%d %d", &n, &m);
for(int i=0;i<n;i++){
scanf("%lld", &a);
insert(a);
}
printf("Case #%d:\n", s);
for(int i=0;i<m;i++){
scanf("%lld", &a);
printf("%d\n", query(a));
}
}
}
#include <bits/stdc++.h>
using namespace std;
#define maxn 1000
#define ll long long
int tol;
ll val[30*maxn];
int ch[30*maxn][2];
int nn[30*maxn][2];
void init(){
tol=1;
memset(nn,0,sizeof nn);
ch[0][0]=ch[0][1]=0;
}
void insert(ll x){
int u=0;
for(int i=30;i>=0;i--){
int v=(x>>i)&1;
nn[u][v]++;
if(!ch[u][v]){
ch[tol][0]=ch[tol][1]=0;
val[tol]=0;
ch[u][v]=tol++;
}
u=ch[u][v];
}
val[u]=x;
}
ll query(ll x){
int u=0;
for(int i=30;i>=0;i--){
int v=(x>>i)&1;
if(ch[u][v^1]&&nn[u][v^1]) u=ch[u][v^1];
else u=ch[u][v];
}
return val[u];
}
void pp(){
for(int i=0;i<tol;i++){
cout<<i<<" "<<nn[i][0]<<" "<<nn[i][1]<<endl;
}
}
ll solve(ll x,ll y){
ll xx=x,yy=y;
ll num=x+y;
ll u=0;
for(int i=30;i>=0;i--){
int v=(x>>i)&1;
nn[u][v]--;
u=ch[u][v];
}
u=0;
for(int i=30;i>=0;i--){
int v=(y>>i)&1;
nn[u][v]--;
u=ch[u][v];
}
ll ans=num^query(num);
u=0;
for(int i=30;i>=0;i--){
int v=(xx>>i)&1;
nn[u][v]++;
u=ch[u][v];
}
u=0;
for(int i=30;i>=0;i--){
int v=(yy>>i)&1;
nn[u][v]++;
u=ch[u][v];
}
return ans;
}
ll a[maxn];
int main(){
int T,n,m;
scanf("%d",&T);
while(T--){
init();
scanf("%d", &n);
for(int i=0;i<n;i++){
scanf("%lld", &a[i]);
insert(a[i]);
}
int ans=0,num;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
num=solve(a[i],a[j]);
if(ans<num) ans=num;
}
}
cout<<ans<<endl;
}
}
字典树
#include <bits/stdc++.h>
using namespace std;
struct node {
int cnt;
node* child[26];
};
node* root;
void init()
{
root=new node();
}
void insert(const char s[])
{
node* now=root;
for(int i=0;s[i];i++){
int go=s[i]-'a';
if(now->child[go]==NULL)
now->child[go]=new node();
now=now->child[go];
now->cnt++;
}
}
int query(const char s[])
{
node* now=root;
for(int i=0;s[i];i++){
int go=s[i]-'a';
if(now->child[go]==NULL) return -1;
now=now->child[go];
}
return now->cnt;
}
void del(const char s[])
{
node* now=root;
for(int i=0;s[i];i++){
int go=s[i]-'a';
if(now->child[go]->cnt==1){
now->child[go]=NULL;
return;
}
now=now->child[go];
now->cnt--;
}
}
int main()
{
init();
insert("abcdef");
insert("abccba");
cout << query("abc") << endl;
cout << query("abcc") << endl;
cout << query("abs") << endl;
cout << query("abcdef") << endl;
del("abcdef");
cout << query("abcdef") << endl;
cout<<query("abc")<<endl;
return 0;
}
并查集
#include <bits/stdc++.h>
using namespace std;
#define maxn 100000
int n,m;
int u,v,k;
int fa[maxn];
void init(){
for(int i=0;i<=n;i++)
fa[i]=i;
}
int root(int x){
return fa[x]==x?x:fa[x]=root(fa[x]);
}
void unite(int u,int v){
u=root(u);
v=root(v);
if(u!=v)
fa[v]=u;
}
bool ailke(int u,int v){
return root(u)==root(v);
}
int main(){
cin>>n>>m;
init();
for(int i=0;i<m;i++){
cin>>k>>u>>v;
if(k==1) unite(u,v);
if(k==2){
if(ailke(u,v)){
cout<<"Y"<<endl;
}else{
cout<<"N"<<endl;
}
}
}
return 0;
}
带权并查集
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 1000000
int fa[maxn];
int group[maxn];
int n,m;
int ans;
int d,x,y;
void init(){
for(int i=0;i<=n;i++){
fa[i]=i;
group[i]=0;
}
ans=0;
}
int root(int x){
if(fa[x]==x)return x;
int r=root(fa[x]);
group[x]=(group[x]+group[fa[x]])%3;
return fa[x]=r;
}
int main(){
scanf("%d%d",&n,&m);
init();
while(m--){
scanf("%d%d%d",&d,&x,&y);
if(x>n||y>n||(d==2&&x==y)){
ans++;
continue;
}
int fx=root(x);
int fy=root(y);
if(fx==fy){
if(d==1) if(group[x]!=group[y]) ans++;
if(d==2) if((3+group[y]-group[x])%3!=1) ans++;
}else{
group[fy]=((d-1)+3+group[x]-group[y])%3;
fa[fy]=fx;
}
}
cout<<ans<<endl;
return 0;
}