这两天在看大纲讲的计算几何,表示懵… 然后LTY大神就给我看了D1T2(BZOJ4552,一会补),A掉后我就去看了T1,两种做法
第一种:链剖 表示并不会
第二种:并查集
自认为并查集学的可以,就开始乱搞,我大概思路是 离线,先把所有操作读入,倒序处理,如果是标记操作 ,那么将这个节点的sum–;如果是查询操作,那么去找他的父亲,看他父亲的sum是否等于0,若等于0,那么我就去合并连通块,将当前的父亲的父亲赋值给读入的关系,并重复上述操作,知道找到sum不为0的祖先,这就是本次查找出的答案,把它记录在ans数组里,因为我们是倒序处理的,要注意输出的顺序。
直接放代码
/**************************************************************
Problem: 4551
User: wbxdhr
Language: C++
Result: Accepted
Time:1012 ms
Memory:3672 kb
****************************************************************/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int dit[100010],rel[100010],sum[100010],fa[100010],qu[100010],ans[100010];
int find(int x)
{
if(fa[x]==x)
{
return x;
}
else
{
fa[x]=find(fa[x]);
return fa[x];
}
}
int main()
{
int n,m,i,a,b,fz,faa,cnt=0;
char s[5];
sum[1]=1000001;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
rel[b]=a;
}
for(i=1;i<=m;i++)
{
scanf("%s%d",s,&a);
dit[i]=a;
if(s[0]=='C')//change
{
qu[i]=1;
sum[a]++;
}
else//find
{
qu[i]=2;
}
}
for(i=0;i<=100009;i++)
{
fa[i]=i;
}
for(i=m;i>=1;i--)
{
if(qu[i]==1)//change
{
sum[dit[i]]--;
if(sum[dit[i]]==0)
{
fa[dit[i]]=rel[dit[i]];
}
}
else//find
{
fz=dit[i];
while(1)
{
faa=find(fz);
if(sum[faa]==0)
{
fa[faa]=rel[faa];
}
else
{
break;
}
}
cnt++;
ans[cnt]=faa;
}
}
for(i=cnt;i>=1;i--)
{
printf("%d\n",ans[i]);
}
return 0;
}
重新贴一份代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int fa[100010],rel[100010],p[100010],num[100010],ans[100010];
bool chg[100010];
int find(int x){
if(fa[x]==x) return x;
else{
fa[x]=find(fa[x]);
return fa[x];
}
}
int main()
{
int n,i,q,a,b,cnt=1,faa; char c[5];
scanf("%d%d",&n,&q);
for(i=1;i<n;i++){
scanf("%d%d",&a,&b);
rel[b]=a;
}
for(i=1;i<=q;i++){
scanf("%s%d",c,&p[i]);
if(c[0]=='C'){
chg[i]=true;
num[p[i]]++;
}
else chg[i]=false;
}
num[1]+=1000000;
for(i=0;i<=n;i++) fa[i]=i;
for(i=q;i>=1;i--)
{
if(chg[i]==true)
{
num[p[i]]--;
if(num[p[i]]<=0) fa[p[i]]=rel[p[i]];
}
else
{
while(1)
{
faa=find(p[i]);
if(num[faa]<=0) fa[faa]=rel[faa];
else break;
}
ans[cnt++]=faa;
}
}
for(i=cnt-1;i>=1;i--) printf("%d\n",ans[i]);
return 0;
}