• P2146 [NOI2015]软件包管理器 树链剖分模板题


    继续复习(预习)

    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5;
    int tr[maxn<<2],lazy[maxn<<2];
    int dep[maxn],fa[maxn],size[maxn],id[maxn],top[maxn],son[maxn];
    int times=0,n;
    int head[maxn];
    struct Node{
    	int next,to;
    }edge[maxn<<1];
    int z=0;
    void add_edge(int x,int y){
    	edge[z].next=head[x];
    	edge[z].to=y;
    	head[x]=z++;
    }
    void dfs1(int x){
    	dep[x]=dep[fa[x]]+1;
    	size[x]=1;
    	for(int i=head[x];i!=-1;i=edge[i].next){
    		int y=edge[i].to;
    		if(y==fa[x])continue;
    		fa[y]=x;
    		dfs1(y);
    		size[x]+=size[y];
    		if(size[son[x]]<size[y])son[x]=y;
    	}
    }
    void dfs2(int x,int tp){
    	top[x]=tp;id[x]=++times;
    	if(son[x]==0)return ;
    	dfs2(son[x],tp);
    	for(int i=head[x];i!=-1;i=edge[i].next){
    		int y=edge[i].to;
    		if(y!=fa[x]&&y!=son[x])dfs2(y,y);
    	}
    }
    void build(int o,int l,int r){
    	tr[o]=0;
    	lazy[o]=-1;
    	if(l==r){
    		return ;
    	}
    	int mid=l+r>>1;
    	build(o<<1,l,mid);
    	build(o<<1|1,mid+1,r);
    }
    void push_down(int o,int len){
    	if(lazy[o]!=-1){
    		lazy[o<<1]=lazy[o];
    		lazy[o<<1|1]=lazy[o];
    		tr[o<<1]=(len-len/2)*lazy[o];
    		tr[o<<1|1]=len/2*lazy[o];
    		lazy[o]=-1;
    	}
    }
    int query(int o,int l,int r,int x,int y){
    	if(x<=l&&y>=r)return tr[o];
    	int mid=l+r>>1;
    	int tmp=0;
    	push_down(o,r-l+1);
    	if(mid>=x)tmp+=query(o<<1,l,mid,x,y);
    	if(mid<y)tmp+=query(o<<1|1,mid+1,r,x,y);
    	return tmp;
    }
    void update(int o,int l,int r,int x,int y,int flag){
    	if(x<=l&&y>=r){
    		tr[o]=(r-l+1)*flag;
    		lazy[o]=flag;
    		return ;
    	}
    	int mid=l+r>>1;
    	//push_down(o,r-l+1);
    	if(mid>=x)update(o<<1,l,mid,x,y,flag);
    	if(mid<y)update(o<<1|1,mid+1,r,x,y,flag);
    	tr[o]=tr[o<<1]+tr[o<<1|1];
    }
    int qrange(int x,int y){
    	int ans=0;
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		ans+=query(1,1,n,id[top[x]],id[x]);
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y])swap(x,y);
    	ans+=query(1,1,n,id[x],id[y]);
    	return ans;
    }
    void updrange(int x,int y,int flag){
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		update(1,1,n,id[top[x]],id[x],flag);
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y])swap(x,y);
    	update(1,1,n,id[x],id[y],flag);
    }
    int dbug(int x){
    	return query(1,1,n,x,x);
    }
    void solve(){
    	char op[20];
    	int x;
    	scanf("%s",&op);
    	scanf("%d",&x);x++;
    	if(op[0]=='i'){
    		printf("%d
    ",dep[x]-qrange(1,x));
    		updrange(1,x,1);
    	}
    	if(op[0]=='u'){
    		printf("%d
    ",query(1,1,n,id[x],id[x]+size[x]-1));
    		update(1,1,n,id[x],id[x]+size[x]-1,0);
    	}
    //	cout<<dbug(1)<<" "<<dbug(2)<<" "<<dbug(3)<<" "<<dbug(4)<<" "<<dbug(5)<<" "<<dbug(6)<<" "<<dbug(6)<<endl;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)head[i]=-1;
    	for(int i=2;i<=n;i++){
    		int x;
    		scanf("%d",&x);x++;
    		add_edge(i,x);add_edge(x,i);
    	}
    	dfs1(1);
    	dfs2(1,1);
    	//for(int i=1;i<=n;i++)cout<<id[i]<<" ";
    	//cout<<endl;
    	//cout<<endl;
    	int q;
    	scanf("%d",&q);
    	while(q--)solve();
    }
    
    
  • 相关阅读:
    《火影忍者:究级风暴》渲染技术究极解析!
    动态数组和内置数组转换范例
    固定视角
    旋转
    时间间隔操作
    编辑器的一些批处理脚本
    访问GUItexture
    血槽制作
    动画循环播放
    软件测试修炼之道之——重现问题(上)
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/12964786.html
Copyright © 2020-2023  润新知