【BZOJ】【P1146】【CTSC2008】【网络管理Network】【题解】【树链剖分+线段树套平衡树】

传送门:

http://www.lydsy.com/JudgeOnline/problem.php?id=1146


蒟蒻刷了两天啊!!!!!!!!!


尼玛两天啊!!!!!!!!!!!


重写三遍啊!!!!!!!!!!!


346行代码啊!!!!!!!!!!


链剖+树套树啊!!!!!!!!!


30sT成翔啊!!!!!!!!!!!


================================================================================================================

感想发表完毕

=================================================================================================================

不多说了,看代码吧,附赠数据生成器

Code:

#include<vector>
#include<cstdio>
#include<climits>
#include<iostream>
#include<algorithm>
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define L (i<<1)
#define R (i<<1|1)
const int maxn=80010;
const int INF=INT_MAX;
using namespace std;
typedef pair<int,int> pii;
vector<int>G[maxn];  
int What;
int dep[maxn],son[maxn],siz[maxn],fa[maxn],top[maxn],w[maxn],z=0,a[maxn],b[maxn];  
int rnd(){
	static int KEY=12345678;
	return KEY+=KEY<<2|1;
}
void add(int u,int v){  
    G[u].push_back(v);  
    G[v].push_back(u);  
}  
int n,m;
pii road[10001];
int Left,Right,Find;
struct Treap{  
    struct node{  
        int val;int key,size,s;  
        node *c[2];  
        node(int _val,node *C){  
            val=_val;key=rand();  
            size=1;s=1;  
            c[0]=c[1]=C;  
        }  
        void rz(){  
            size=c[0]->size+c[1]->size+s;  
        }  
    };  
    node *root,*Null;  
    Treap(){  
        Null=new node(0,0);  
        Null->size=0;Null->key=INF;Null->val=0;  
        Null->c[0]=Null->c[1]=Null;  
        root=Null;  
    }  
    void rot(node *&t,bool d){  
        node *p=t->c[d];  
        t->c[d]=p->c[!d];  
        p->c[!d]=t;  
        t->rz();p->rz();  
        t=p;  
    }  
    void _insert(node *&t,int x){  
        if(t==Null){  
            t=new node(x,Null);  
            return ;  
        }     
        if(t->val==x){  
            t->s++;  
            t->size++;  
            return;  
        }  
        bool d=x>t->val;  
        _insert(t->c[d],x);  
        if(t->c[d]->key<t->key)  
            rot(t,d);  
        else  
            t->rz();  
    }  
    void _Delete(node *&t,int x){  
        if(t==Null)return;  
        if(t->val==x){  
            if(t->s>1){  
                t->s--;  
                t->size--;  
                return;  
            }  
            bool d=t->c[1]->key<t->c[0]->key;  
            if(t->c[d]==Null){  
                delete t;  
                t=Null;  
                return ;  
            }  
            rot(t,d);  
            _Delete(t->c[!d],x);  
        }else{  
            bool d=x>t->val;  
            _Delete(t->c[d],x);  
        }  
        t->rz();  
    }  
    int _kth(node *&t,int x){  
        int r=t->c[0]->size;  
        if(t==Null)return 0;  
        else if(x<=r)return _kth(t->c[0],x);  
        else if(x>r+t->s)return _kth(t->c[1],x-r-t->s);  
        else return t->val;  
    }  
    int _rank(node *&t,int x){  
        int r=t->c[0]->size;  
        if(t==Null)return 0;  
        else if(x==t->val){Find=1;return r;} 
        else if(x>t->val){Right++;return r+t->s+_rank(t->c[1],x);}
        else{Left++;return _rank(t->c[0],x);}   
    }  
    void _deb(node *&t){  
        printf("val:%d L:%d R:%d\n",t->val,t->c[0]->val,t->c[1]->val);  
        //printf("key:%d L:%d R:%d\n",t->key,t->c[0]->key,t->c[1]->key);  
        printf("size:%d L:%d R:%d\n",t->size,t->c[0]->size,t->c[1]->size);  
        if(t->c[0]!=Null)_deb(t->c[0]);  
        if(t->c[1]!=Null)_deb(t->c[1]);  
    }  
    void deb(){_deb(root);puts("");}  
    void insert(int x){_insert(root,x);}  
    void del(int x){_Delete(root,x);}  
    int kth(int x){return _kth(root,x);}  
    int rank(int x){return _rank(root,x);}  
    int size(){return root->size;}  
    int _prev(node *&t,int x){  
        if(t==Null)return INT_MIN;  
        if(x<=t->val)return _prev(t->c[0],x);  
        return max(t->val,_prev(t->c[1],x));  
    }  
    int _next(node *&t,int x){  
        if(t==Null)return INT_MAX;  
        if(x>=t->val)return _next(t->c[1],x);  
        return min(t->val,_next(t->c[0],x));  
    }  
    int prev(int x){  
        return _prev(root,x);  
    }  
    int next(int x){  
        return _next(root,x);  
    }   
};  
struct seg_tree{
	Treap t[maxn<<2];
	void build(int i,int l,int r){
		if(l>r)return;		
		for(int o=l;o<=r;o++){
			t[i].insert(a[o]);
			printf("#%d  o:%d a[o]:%d",i,o,a[o]);
		}
		if(l==r)return;
		int mid=l+r>>1;
		build(lson);
		build(rson);
	}
	void change(int i,int l,int r,int pos,int val){
		if(l>r)return;
		//printf("#%d pos:%d val:%d\n",i,pos,val);
		//puts("old");
		//t[i].deb();
		t[i].del(a[pos]);
		//a[pos]=val;
		//puts("new");
		t[i].insert(val);
		//t[i].deb();
		if(l==r){
			a[pos]=val;
			return;
		}
		int mid=l+r>>1;
		if(pos<=mid)change(lson,pos,val);
		else change(rson,pos,val);
	}
	int rank(int i,int l,int r,int l0,int r0,int k){
		if(l>r)return 0;
		int ans=0;
		if(l0<=l&&r0>=r)
			return t[i].rank(k);
		int mid=l+r>>1;
		if(l0<=mid)ans+=rank(lson,l0,r0,k);
		if(r0>mid) ans+=rank(rson,l0,r0,k);
		return ans;
	}
	int prev(int i,int l,int r,int l0,int r0,int k){
		if(l>r)return 0;
		int ans=INT_MIN;
		if(l0<=l&&r0>=r)
			return t[i].prev(k);
		int mid=l+r>>1;
		if(l0<=mid)ans=max(ans,prev(lson,l0,r0,k));
		if(r0>mid) ans=max(ans,prev(rson,l0,r0,k));
		return ans;	
	}
	int next(int i,int l,int r,int l0,int r0,int k){
		if(l>r)return 0;
		int ans=INT_MAX;
		if(l0<=l&&r0>=r)
			return t[i].next(k);
		int mid=l+r>>1;
		if(l0<=mid)ans=min(ans,next(lson,l0,r0,k));
		if(r0>mid) ans=min(ans,next(rson,l0,r0,k));
		return ans;	
	}
}T;
namespace TRT{
	void Change(int pos,int k){
		T.change(1,1,n,pos,k);		
	}
	int Rank(int l,int r,int k){
		Left=Right=Find=0;
		int res=T.rank(1,1,n,l,r,k);
		if(Find)return res;
		if(Left==0)return res;
		if(Right==0)return res-1;
		return res;
	}
	int kth(int l0,int r0,int k){
		int l=0,r=int(1e8)+10;
		while(l<r){
			int mid=l+r>>1;
	
			if(Rank(l0,r0,mid)<=k)
				l=mid+1;
			else
				r=mid;
		}
		return l-1;
	}
	int prev(int l,int r,int k){
		return T.prev(1,1,n,l,r,k);
	}
	int next(int l,int r,int k){
		return T.next(1,1,n,l,r,k);
	}
};
namespace TOPL{

	void dfs(int u){  
	    son[u]=0;siz[u]=1;  
	    for(int i=0;i<G[u].size();i++){  
	        int v=G[u][i];  
	        if(v!=fa[u]){  
	            dep[v]=dep[u]+1;  
	            fa[v]=u;  
	            dfs(v);  
	            if(siz[v]>siz[son[u]])son[u]=v;  
	            siz[u]+=siz[v];  
	        }  
	    }  
	}  
	void build(int u,int tp){  
	    w[u]=++z;top[u]=tp;  
	    if(son[u])build(son[u],tp);  
	    for(int i=0;i<G[u].size();i++){  
	        int v=G[u][i];  
	        if(v!=fa[u]&&v!=son[u])  
	        build(v,v);  
	    }  
	}  
	void Change(int pos,int val){
		TRT::Change(w[pos],val);
	}
	int len(int u,int v){
		What=0;
		while(top[u]!=top[v]){
			if(dep[top[u]]>dep[top[v]]){
				road[++What]=pii(u,top[u]);
				u=fa[top[u]];
			}else{
				road[++What]=pii(v,top[v]);
				v=fa[top[v]];
			}
		}
		road[++What]=pii(u,v);
		int ans=0;
		for(int i=1;i<=What;i++){
			u=road[i].first;v=road[i].second;
			if(u>v)swap(u,v);
			
			ans+=abs(dep[u]-dep[v])+1;
			
		}	
		return ans;
	}
	int Rank(int u,int v,int k){
		What=0;int tmp;
		while(top[u]!=top[v]){
			if(dep[top[u]]>dep[top[v]]){
				road[++What]=pii(w[u],w[top[u]]);
				u=fa[top[u]];
			}else{
				road[++What]=pii(w[v],w[top[v]]);
				v=fa[top[v]];
			}
		}
		road[++What]=pii(w[u],w[v]);
		int ans=0;
		for(int i=1;i<=What;i++){
			u=road[i].first;v=road[i].second;
			if(u>v)swap(u,v);
			
			tmp=TRT::Rank(u,v,k);
			if(~tmp)ans+=tmp;
		}	
		return ans;
	}
	void Kth(int u,int v,int k){
		k=len(u,v)-k+1;if(k<=0){
			puts("invalid request!");return;
		}
		int l=0,r=(1e8),mid;
		while(l<r){
			mid=l+r>>1;
			int rr=Rank(u,v,mid);
			if(rr<k)
				l=mid+1;
			else
				r=mid;
		}
		printf("%d\n",l-1);
	}
};
int main(){
	scanf("%d%d",&n,&m);

	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=a[i];
		a[i]=-1;
			//	Change(i,a[i]);
	}	
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v);
	}
	TOPL::dfs(1);TOPL::build(1,1);
	for(int i=1;i<=n;i++){
		TOPL::Change(i,b[i]);
	}	
	int k,a,b;
	while(m--){
		scanf("%d%d%d",&k,&a,&b);
		if(k==0){
			TOPL::Change(a,b);
		}else{
			TOPL::Kth(a,b,k);
		}
	}
	return 0;
} 


附赠数据生成器:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<ctime>
#include<algorithm>
using namespace std;
int main(){
	int a[2101];
	srand(time(0));
	freopen("1.txt","w",stdout);
	int n=500,m=1000;
	cout<<n<<" "<<m<<endl;
	for(int i=1;i<=n;i++)
	cout<<(a[i]=rand()%5+1)<<" ";
	cout<<endl;
	for(int i=2;i<=n;i++){
		cout<<i<<" "<<rand()%(i-1)+1<<endl;
	}
	while(m--){
		int l=rand()%n+1;
		int r=rand()%n+1;
		if(l>r)swap(l,r);
		int k=rand()%(r-l+1);
		
		cout<<k<<" "<<l<<" "<<r<<endl;

	}
	return 0;
}



你可能感兴趣的:(bzoj,省选)