大概对dalao们而言的确是基本了
可是我只觉得这简直 基(变)本(态)
题面的话 要求操作如下
然后据说dalao们都在打主席树然而垃圾并不懂那是什么
上次打树剖题也有蛮久了忘得差不多了qwq
还好有强行不超纲的出题人救我等渣渣于水深火热之中
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define maxn 150000
#define ls x<<1
#define rs x<<1|1
using namespace std;
int head[maxn],to[maxn],nxt[maxn],tot;
int tree[maxn*4],sz[maxn],tp[maxn],son[maxn];
int fa[maxn],ed[maxn],dfn[maxn];
int de[maxn],df=0,n,ans[maxn],m1,m;
struct hh {
int id,x,y,z,t;
} g[maxn];
void link(int x,int y) {
nxt[++tot]=head[x];
to[tot]=y;
head[x]=tot;
}
void update(int x,int l,int r,int xx,int v) {
if (l==r) {
tree[x]=v;
return ;
}
int mid=(l+r)>>1;
if (xx<=mid) update(ls,l,mid,xx,v);
else update(rs,mid+1,r,xx,v);
tree[x]=tree[ls]+tree[rs];
}
int query(int x,int l,int r,int ll,int rr) {
if (ll<=l&&r<=rr) return tree[x];
int mid=(l+r)>>1;
int ans=0;
if (ll<=mid) ans+=query(ls,l,mid,ll,rr);
if (rr>mid) ans+=query(rs,mid+1,r,ll,rr);
return ans;
}
void dfs(int x) {
sz[x]++;
for (int i=head[x]; i; i=nxt[i]) {
int t=to[i];
if (t==fa[x])continue;
fa[t]=x;
de[t]=de[x]+1;
dfs(t);
sz[x]+=sz[t];
if (sz[t]>sz[son[x]]) son[x]=t;
}
}
void dfs2(int x,int top) {
tp[x]=top;
dfn[x]=++df;
if (son[x]) dfs2(son[x],top);
for (int i=head[x]; i; i=nxt[i]) {
int t=to[i];
if (t==fa[x]||t==son[x])continue;
dfs2(t,t);
}
ed[x]=df;
}
int doit(int x,int y) {
int ans=0;
while (tp[x]!=tp[y]) {
if (de[tp[x]]<de[tp[y]]) swap(x,y);
ans+=query(1,1,n,dfn[tp[x]],dfn[x]);
x=fa[tp[x]];
}
if (de[x]>de[y]) swap(x,y);
ans+=query(1,1,n,dfn[x],dfn[y]);
return ans;
}
bool comp(hh a,hh b) {
if (a.z!=b.z) return a.z<b.z;
else return a.id<b.id;
}
int main() {
scanf ("%d",&n);
for (int i=1; i<n; ++i) {
int x,y;
scanf ("%d%d",&x,&y);
link(x,y);
link(y,x);
}
de[1]=1,dfs(1),dfs2(1,1);
scanf ("%d",&m1);
for (int i=1; i<=m1; ++i) {
int x;
scanf ("%d",&x);
int y,z;
if (x==1) {
scanf ("%d%d",&y,&z);
update(1,1,n,dfn[y],z);
}
if (x==2) {
scanf ("%d%d",&y,&z);
cout<<doit(y,z)<<endl;
}
if (x==3) {
scanf ("%d",&y);
cout<<query(1,1,n,dfn[y],ed[y])<<endl;
}
}
scanf ("%d",&m);
for (int i=1; i<=m; ++i) {
int x;
scanf ("%d",&x);
g[i].id=x,g[i].t=i;
if (x==1) {
scanf("%d%d%d",&g[i].x,&g[i].y,&g[i].z);
}
if (x==2) {
scanf ("%d%d",&g[i].x,&g[i].z);
}
}
for (int i=1; i<=n; ++i)
g[++m].id=0,g[m].x=dfn[i],g[m].z=query(1,1,n,dfn[i],dfn[i]);
sort(g+1,g+m+1,comp);
memset(tree,0,sizeof(tree));
for (int i=1; i<=m; ++i) {
if (g[i].id==0) update(1,1,n,g[i].x,1);
if (g[i].id==1) ans[g[i].t]=doit(g[i].x,g[i].y);
else ans[g[i].t]=query(1,1,n,dfn[g[i].x],ed[g[i].x]);
}
for (int i=1; i<=m-n; ++i) cout<<ans[i]<<endl;
return 0;
}
考场上前30分都没拿到实在是比较可惜
打到了doit里面就开始懵逼 不记得dfn在哪里求的来着了
老了老了脑子也不怎么好使了qwq
另外第二问的处理方式简直太dio了!不由得惊叹= =
声明一下 我代码也是学的标程啊!