「yyOI R1」youyou 的军训
Lofi_sicker · · 题解
给一篇不用倍增的题解。
题意
给定一个无向图,每次在原图基础上删去所有边权小于
题解
可以发现,删完边以后最多只有
定义
但这样还不够,空间复杂度不能接受,用可持久化数组就太过麻烦了。考虑直接将询问离线,在每次
时间复杂度
代码
#include<bits/stdc++.h>
using namespace std;
const int Size=(1<<20)+1;
char buf[Size],*p1=buf,*p2=buf;
char buffer[Size];
int op1=-1;
const int op2=Size-1;
inline char readchar(){
if(p1!=p2) {
return *p1++;
}
return p1==(p2=(p1=buf)+fread(buf,1,Size-1,stdin))?EOF:*p1++;
}
inline void flush(){
fwrite(buffer,1,op1+1,stdout),op1=-1;
}
inline void writechar(const char &x) {
if(op1==op2) flush();
buffer[++op1]=x;
}
#ifndef ONLINE_JUDGE
#define readchar getchar
#endif
#define putchar writechar
inline int read() {
int s=1,c=readchar(),x=0;
while(c<=32) {
c=readchar();
}
if(c=='-') {
s=-1,c=readchar();
}
for(; ('0'<=c && c<='9'); c=readchar()) {
x=x*10+c-'0';
}
return x*s;
}
inline void print(long long x) {
if(x<0) {
writechar('-'),x=-x;
}
char s[25];
int n=0;
while(x||!n) {
s[n++]='0'+x%10,x/=10;
}
while(n--) {
writechar(s[n]);
}
}
const int N=4e5+5;
int n,m,T,i,j,rk[N],ans[N],cnt,opt,x,y,l,r,mid,len,fa[N],siz[N];
struct ed{
int x,y,k,id;
}a[N];
struct nd{
int id,val;
};
vector<nd>g[N];
inline bool cmp(ed x,ed y){
return x.k>y.k;
}
inline int find(int x){
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
signed main() {
n=read();m=read();T=read();
for(i=1;i<=m;i++){
a[i].x=read();a[i].y=read();
a[i].k=read();a[i].id=i;
}
sort(a+1,a+m+1,cmp);
for(i=1;i<=m;i++)
rk[a[i].id]=i;
int cur=m;
for(i=1;i<=T;i++){
opt=read();x=read();
if(opt==1){
l=1;r=m;
int ans=0;
while(l<=r){//二分出要保留几条边
mid=l+r>>1;
if(a[mid].k>=x){
l=mid+1;
ans=mid;
}
else r=mid-1;
}
cur=ans;
}
else if(opt==2){
nd tmp;
tmp.id=++len;tmp.val=x;
g[cur].push_back(tmp);
}
else a[rk[x]].k=read();
}
for(i=1;i<=n;i++)fa[i]=i,rk[i]=siz[i]=1;//注意,这里的rk数组用于并查集按秩合并,为了省空间用了相同的数组
for(auto i:g[0])ans[i.id]=1;
for(i=1;i<=m;i++){
int fx=find(a[i].x),fy=find(a[i].y);
if(fx!=fy){//按秩合并
if(rk[fx]<=rk[fy])fa[fy]=fx,siz[fx]+=siz[fy];
else fa[fy]=fx,siz[fy]+=siz[fx];
if(rk[fx]==rk[fy]&&fx!=fy)rk[fy]++;
}
for(auto j:g[i])
ans[j.id]=siz[find(j.val)];
}
for(i=1;i<=len;i++)
print(ans[i]),putchar('\n');
flush();
return 0;
}