• codevs 1490 【CTSC2008】 网络管理


    题目链接:网络管理

      好久没写这种类型的题了……手都生了……

      一句话题意:树上带修改的路径(k)大数。这题面怎么有点眼熟

      显然树上的题目我们可以先在序列上考虑一下。区间带修改的区间(k)大数有两种做法(我只知道两种):一种是树套树,一种是整体二分。这道题感觉如果是树套树的话加到树上会很麻烦,于是就写了整体二分。(不过感觉好像CDQ分治啊

      序列问题和普通的整体二分没有什么区别,只是要注意一个修改操作需要拆成两个,一个操作是把原来的数删掉,下一个才是改为这个数。这样的话就可以保证一个元素的加入和删除永远会在分治时分进同一边,这样才可以保证正确性。到了树上,我们可以令$a_i$表示点$i$到根的路径上的权值,于是就可以求出$dfs$序后使用树状数组很方便的进行维护了。需要区间修改和单点查询,将原数组查分一下用树状数组维护即可。我会和你们说这道板子题我调了整整一天吗

      原谅我这篇博客不讲整体二分的入门

      入门的话我给附一个神犇lightgod的博客

      下面贴代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define maxn 80010
    #define maxm 150010
    
    using namespace std;
    typedef long long llg;
    
    struct data{
    	int k,a,b,id,g;//-1表示减,0表示加
    }s[maxm],zl[maxm],zr[maxm];
    int n,m,le[maxn],ri[maxn],ls,d[maxm],ld,a[maxn];
    int head[maxn],next[maxn<<1],to[maxn<<1],tt;
    int fa[maxn],siz[maxn],top[maxn],son[maxn],dep[maxn];
    int c[maxn],ans[maxn];
    
    int getint(){
    	int w=0;bool q=0;
    	char c=getchar();
    	while((c>'9'||c<'0')&&c!='-') c=getchar();
    	if(c=='-') c=getchar(),q=1;
    	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    	return q?-w:w;
    }
    
    void link(int x,int y){
    	to[++tt]=y;next[tt]=head[x];head[x]=tt;
    	to[++tt]=x;next[tt]=head[y];head[y]=tt;
    }
    
    void dfs(int u){
    	siz[u]=1; le[u]=++tt;
    	for(int i=head[u],v;v=to[i],i;i=next[i])
    		if(v!=fa[u]){
    			fa[v]=u; dfs(v); siz[u]+=siz[v];
    			if(siz[v]>siz[son[u]]) son[u]=v;
    		}
    	ri[u]=tt;
    }
    
    void dfs(int u,int t){
    	top[u]=t; dep[u]=dep[fa[u]]+1;
    	if(son[u]) dfs(son[u],t);
    	for(int i=head[u],v;v=to[i],i;i=next[i])
    		if(!top[v]) dfs(v,v);
    }
    
    void add(int x,int y){while(x<=n) c[x]+=y,x+=x&(-x);}
    int sum(int x){
    	int t=0;
    	while(x) t+=c[x],x-=x&(-x);
    	return t;
    }
    
    void solve(int top,int end,int l,int r){
    	if(l==r){
    		for(int i=top;i<=end;i++)
    			if(s[i].id) ans[s[i].id]=d[l];
    		return;
    	}
    	int mid=(l+r+1)>>1,lo(0),ro(0);
    	bool ll(0),rr(0);
    	for(int i=top,u,x;i<=end;i++){
    		if(s[i].k<=0){
    			if(s[i].b>=d[mid]){
    				u=s[i].a; zr[++ro]=s[i];
    				if(!s[i].k) add(le[u],1),add(ri[u]+1,-1);
    				else add(le[u],-1),add(ri[u]+1,1);
    			}
    			else zl[++lo]=s[i];
    		}
    		else{
    			x=sum(le[s[i].a])+sum(le[s[i].b]);
    			x-=sum(le[s[i].g])+sum(le[fa[s[i].g]]);
    			if(x>=s[i].k) zr[++ro]=s[i],rr=1;
    			else s[i].k-=x,zl[++lo]=s[i],ll=1;
    		}
    	}
    	for(int i=top,u;i<=end;i++)
    		if(s[i].k<=0 && s[i].b>=d[mid]){
    			u=s[i].a;
    			if(!s[i].k) add(le[u],-1),add(ri[u]+1,1);
    			else add(le[u],1),add(ri[u]+1,-1);
    		}
    	for(int i=1;i<=lo;i++) s[i+top-1]=zl[i];
    	for(int i=1;i<=ro;i++) s[i+top+lo-1]=zr[i];
    	if(ll) solve(top,top+lo-1,l,mid-1);
    	if(rr) solve(top+lo,end,mid,r);
    }
    
    int lca(int u,int v){
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]]) swap(u,v);
    		u=fa[top[u]];
    	}
    	if(dep[u]<dep[v]) swap(u,v);
    	return v;
    }
    
    int main(){
    	File("a");
    	n=getint(); m=getint(); ls=n;
    	for(int i=1;i<=n;i++){
    		s[i].k=0,s[i].a=i,s[i].b=getint();
    		d[++ld]=a[i]=s[i].b;
    	}
    	for(int i=1;i<n;i++) link(getint(),getint());
    	tt=0; dfs(1); dfs(1,1); tt=0;
    	for(int i=1;i<=m;i++){
    		s[++ls].k=getint(); s[ls].a=getint(); s[ls].b=getint();
    		if(s[ls].k){
    			s[ls].id=++tt; s[ls].g=lca(s[ls].a,s[ls].b);
    			if(dep[s[ls].a]+dep[s[ls].b]-2*dep[s[ls].g]+1<s[ls].k)
    				ans[tt]=-1,s[ls].id=0,ls--;
    		}
    		else{
    			ls++; s[ls]=s[ls-1]; s[ls-1].k=-1;
    			s[ls-1].b=a[s[ls].a]; a[s[ls].a]=s[ls].b;
    			d[++ld]=s[ls].b;
    		}
    	}
    	sort(d+1,d+ld+1); ld=unique(d+1,d+ld+1)-d-1;
    	solve(1,ls,1,ld);
    	for(int i=1;i<=tt;i++)
    		if(ans[i]==-1) printf("invalid request!
    ");
    		else printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    c#可以做什么
    C#是否快被年代所筛选?
    在.NET程序中,C#办法可用来封装代码
    关于程序员的小故事
    码农需了解的代码编写标准
    关于HTML代码的技巧
    分析一波编程语言的前景
    彻底解决Linux索引节点(inode)占用率高的告警
    Python29之字符str与字节bytes
    Python28之文件1
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6241456.html
Copyright © 2020-2023  润新知