【Luogu】P2146软件包管理器(树链剖分)
上午跟rqy学了一道超难的概率题,准备颓一会,于是水了这么一道水题。
话说这题真的是模板啊。数据范围正好,描述特别贴近(都不给你绕弯子的),连图都给你画出来,就差题目描述加一句“树链剖分模板”了qwq
怕当年考noi的选手想不到这是树剖么qwq
然后一般来讲省选及以上难度的题都是有套路的,也就是说你秒出的算法都过不了,比如轮状病毒肯定秒出高斯消元解行列式,然后就过不了了
emm但是这个为什么是真的模板啊qwq
我交之前还想着“没事,肯定被卡。我只看看我树剖暴力能拿几分”
然后就A了啊喂。
#include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<algorithm> #define maxn 300050 #define left (rt<<1) #define right (rt<<1|1) #define mid ((l+r)>>1) #define lson l,mid,left #define rson mid+1,r,right using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int n; int deep[maxn]; int top[maxn]; int father[maxn]; int dfn[maxn],ID; int back[maxn]; int size[maxn]; int son[maxn]; struct Edge{ int next,to; }edge[maxn*3]; int head[maxn],num; inline void add(int from,int to){ edge[++num]=(Edge){head[from],to}; head[from]=num; } void findfs(int x,int fa){ deep[x]=deep[fa]+1; father[x]=fa; size[x]=1; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==fa) continue; findfs(to,x); size[x]+=size[to]; if(son[x]==0||size[son[x]]<size[to]) son[x]=to; } } void unidfs(int x,int Top){ dfn[x]=++ID; back[ID]=1; top[x]=Top; if(!son[x]) return; unidfs(son[x],Top); for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==father[x]||to==son[x]) continue; unidfs(to,to); } } int tree[maxn*10],tag[maxn*10]; inline void pushup(int rt){ tree[rt]=tree[left]+tree[right]; } void pushdown(int rt,int m){ if(tag[rt]==-1) return; tag[left]=tag[rt]; tag[right]=tag[rt]; tree[left]=tag[rt]*(m-(m>>1)); tree[right]=tag[rt]*(m>>1); tag[rt]=-1; return; } void update(int from,int to,int num,int l,int r,int rt){ if(from<=l&&to>=r){ tree[rt]=num*(r-l+1); tag[rt]=num; return; } pushdown(rt,r-l+1); if(from<=mid) update(from,to,num,lson); if(to>mid) update(from,to,num,rson); pushup(rt); return; } void updatesum(int from,int to,int num){ while(top[from]!=top[to]){ if(deep[top[from]]<deep[top[to]]) swap(from,to); update(dfn[top[from]],dfn[from],num,1,n,1); from=father[top[from]]; } if(deep[from]>deep[to]) swap(from,to); update(dfn[from],dfn[to],num,1,n,1); return; } int query(int from,int to,int l,int r,int rt){ if(from<=l&&to>=r) return tree[rt]; int ans=0; pushdown(rt,r-l+1); if(from<=mid) ans+=query(from,to,lson); if(to>mid) ans+=query(from,to,rson); return ans; } int querysum(int from,int to){ int ans=0; while(top[from]!=top[to]){ if(deep[top[from]]<deep[top[to]]) swap(from,to); ans+=query(dfn[top[from]],dfn[from],1,n,1); from=father[top[from]]; } if(deep[from]>deep[to]) swap(from,to); ans+=query(dfn[from],dfn[to],1,n,1); return ans; } void updatetree(int from,int num){ update(dfn[from],dfn[from]+size[from]-1,num,1,n,1); } int querytree(int from){ return query(dfn[from],dfn[from]+size[from]-1,1,n,1); } int main(){ memset(tag,-1,sizeof(tag)); n=read(); for(int i=1;i<n;++i){ int x=read(); add(x+1,i+1); add(i+1,x+1); } findfs(1,1); unidfs(1,1); int m=read(); for(int i=1;i<=m;++i){ char ch[100];int x; scanf("%s%d",ch,&x); x++; if(ch[0]=='i'){ int last=querysum(1,x); updatesum(1,x,1); int now=querysum(1,x); printf("%d\n",now-last); } else{ int last=querytree(x); updatetree(x,0); int now=querytree(x); printf("%d\n",last-now); } } return 0; }