zoukankan      html  css  js  c++  java
  • BZOJ4448 SCOI2015 情报传递

    传送门

    题目大意

    给定一棵树,支持两种操作:将一个点染黑,询问路径上在$k$步操作前就已经被染黑的点的数量。

    题解

    将染黑看做给一个点赋其操作编号点权,每次询问路径上点权小于一定值的数量。

    这样会有一个性质,由于$k>0$,所以我们完全可以在查询之前将所有点权赋上。

    所以只需要离线然后查询就好了,可以在树上利用差分主席树维护。

    #include<algorithm>
    #include<iostream>
    #include<cassert>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define M 300020
    using namespace std;
    namespace IO{
    	const int BS=(1<<20); int Top=0;
    	char Buffer[BS],OT[BS],*OS=OT,*HD,*TL,SS[20]; const char *fin=OT+BS-1;
    	char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return *HD++;}
    	void flush(){fwrite(OT,1,OS-OT,stdout);}
    	void Putchar(char c){*OS++ =c;if(OS==fin)flush(),OS=OT;}
    	void write(int x){
    		if(!x){Putchar('0');return;}
    		while(x) SS[++Top]=x%10,x/=10;
    		while(Top) Putchar(SS[Top]+'0'),--Top;
    	}
    	int read(){
    		int nm=0,fh=1; char cw=Getchar();
    		for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
    		for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
    		return nm*fh;
    	}
    }
    using namespace IO;
    int n,m,rt[M],L[M*22],R[M*22],sum[M*22],fs[M],nt[M],to[M],tmp,cnt;
    int sz[M],mxs[M],tp[M],fa[M],dep[M],Root,u[M],v[M],c[M],T,col[M];
    void link(int x,int y){nt[tmp]=fs[x],fs[x]=tmp,to[tmp++]=y;}
    void ins(int &x,int pre,int l,int r,int pos){
    	x=++cnt,L[x]=L[pre],R[x]=R[pre]; sum[x]=sum[pre]+1;
    	if(l==r) return; int mid=((l+r)>>1);
    	if(pos<=mid) ins(L[x],L[pre],l,mid,pos);
    	else ins(R[x],R[pre],mid+1,r,pos);
    }
    int calc(int t1,int t2,int d1,int d2){return sum[t1]+sum[t2]-sum[d1]-sum[d2];}
    int qry(int t1,int t2,int d1,int d2,int l,int r,int pos){
    	int now=calc(t1,t2,d1,d2),mid=((l+r)>>1);
    	if(l>=pos||!now) return 0; if(r<pos) return now;
    	int ans1=qry(L[t1],L[t2],L[d1],L[d2],l,mid,pos);
    	int ans2=qry(R[t1],R[t2],R[d1],R[d2],mid+1,r,pos);
    	return ans1+ans2;
    }
    void dfs1(int x){
    	sz[x]=1,dep[x]=dep[fa[x]]+1;
    	for(int i=fs[x];i!=-1;i=nt[i]){
    		dfs1(to[i]),sz[x]+=sz[to[i]];
    		if(sz[mxs[x]]<sz[to[i]]) mxs[x]=to[i];
    	}
    }
    void dfs2(int x,int dtp){
    	tp[x]=dtp,ins(rt[x],rt[fa[x]],1,T,col[x]);if(mxs[x]) dfs2(mxs[x],dtp);
    	for(int i=fs[x];i!=-1;i=nt[i]) if(to[i]!=mxs[x]) dfs2(to[i],to[i]);
    }
    int lca(int x,int y){
    	while(tp[x]!=tp[y]){if(dep[tp[x]]<dep[tp[y]]) swap(x,y); x=fa[tp[x]];}
    	return dep[x]<dep[y]?x:y;
    }
    int main(){
    	n=read(),memset(fs,-1,sizeof(fs));
    	for(int i=1;i<=n;i++) if(!(fa[i]=read())) Root=i;else link(fa[i],i);
    	T=read();
    	for(int i=1;i<=n;i++) col[i]=T;
    	for(int i=1;i<=T;i++){
    		int tpe=read(),x;
    		if(tpe==2){x=read(),col[x]=min(col[x],i);continue;}
    		m++,u[m]=read(),v[m]=read(),c[m]=read(),c[m]=i-c[m];
    	} dfs1(Root),dfs2(Root,Root);
    	for(int i=1;i<=m;i++){
    		int x=u[i],y=v[i],k=lca(u[i],v[i]);
    		write(dep[x]+dep[y]-(dep[k]<<1)+1),Putchar(' ');
    		write(qry(rt[x],rt[y],rt[k],rt[fa[k]],1,T,c[i])),Putchar('
    ');
    	} flush(); return 0;
    }
  • 相关阅读:
    [转] Oracle数据库备份与恢复
    Oracle RMAN 恢复控制文件到指定的路径
    [转] AIX lv 4k偏移量
    关于oracle 10g creating datafile with zero offset for aix
    linux中的chage命令
    [转] Oracle sql 查询突然变慢 -- 案例分析
    [转] Oracle analyze table 使用总结
    [转] Oracle analyze 命令分析
    .net 事务
    _BIN 二进制排序
  • 原文地址:https://www.cnblogs.com/OYJason/p/9809892.html
Copyright © 2011-2022 走看看