• BZOJ3435: [Wc2014]紫荆花之恋


    BZOJ3435: [Wc2014]紫荆花之恋

    https://lydsy.com/JudgeOnline/problem.php?id=3435

    分析:

    • 如果不强制在线,可以将树存下来用点分树来查询和修改。
    • (dis(i,j)-R_jle R_i),是个使用点分树维护的经典问题。
    • 如果每次直接插到父亲下面会使得点分树不平衡,利用替罪羊重构的思想在不平衡的时候重构一下即可,这里重构一下即对这个子树(连通块)进行点分治。
    • 内层如果用线段树会炸空间,于是我内层也使用替罪羊来维护。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    #include <vector>
    using namespace std;
    #define N 100050
    #define M 14000000
    #define ls ch[p][0]
    #define rs ch[p][1]
    #define get(x) (ch[f[x]][1]==x)
    typedef long long ll;
    #define AL1 0.8
    #define AL2 0.9
    char buf[100000],*p1,*p2;
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) 
    int rd() {
    	int x=0,f=1; char s=nc();
    	while(s<'0') {if(s=='-') f=-1; s=nc();}
    	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    	return x*f;
    }
    int head[N],to[N<<1],nxt[N<<1],fa[N][20],Lg[N],dep[N],cnt;
    ll dis[N];
    int sz[M],rr[N],ch[M][2],f[M],val[M],reimu,n,fb[N],tot;
    int Sta[M],top;
    vector<int>V[N];
    int all[N],vis[N],visc,siz[N],fk[N],rot,used[N];
    #define GG(p) (max(sz[ls],sz[rs])>AL1*sz[p])
    inline void add(int u,int v) {
    	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    int newnode(int v) {
    	int p;
    	if(!top) p=++reimu;
    	else {
    		p=Sta[top--];
    		sz[p]=ls=rs=f[p]=0;
    	}
    	val[p]=v;
    	return p;
    }
    int S[M],tp,koishi;
    struct SGT {
    	int root;
    	void insert(int &p,int v,int fa) {
    		if(!p) {
    			p=newnode(v); sz[p]=1; f[p]=fa; return ;
    		}
    		sz[p]++;
    		if(val[p]>v) insert(ls,v,p);
    		else insert(rs,v,p);
    		if(GG(p)) koishi=p;
    	}
    	int ask(int p,int x) {
    		if(!p) return 0;
    		if(val[p]<=x) return ask(rs,x)+sz[ls]+1;
    		else return ask(ls,x);
    	}
    	void dfs(int p) {
    		if(ls) dfs(ls);
    		S[++tp]=p;
    		if(rs) dfs(rs);
    	}
    	int build(int l,int r,int fa) {
    		int mid=(l+r)>>1,p=S[mid];
    		f[p]=fa; ls=rs=0;
    		if(!f[p]) root=p;
    		if(l<mid) ls=build(l,mid-1,p);
    		if(r>mid) rs=build(mid+1,r,p);
    		sz[p]=sz[ls]+sz[rs]+1;
    		return p;
    	}
    	void Ins(int v) {
    		koishi=0;
    		insert(root,v,0);
    		if(koishi) {
    			tp=0;
    			int k=get(koishi),fa=f[koishi];
    			dfs(koishi); 
    			ch[fa][k]=build(1,tp,fa);
    		}
    	}
    	void asd(int p) {
    		if(ls) asd(ls);
    		Sta[++top]=p;
    		if(rs) asd(rs);
    	}
    	void rec() {
    		asd(root); root=0;
    	}
    }F[N][2];
    int lca(int x,int y) {
    	int i;
    	if(dep[x]<dep[y]) swap(x,y);
    	for(i=Lg[dep[x]];i>=0;i--) {
    		if(fa[x][i]&&dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    	}
    	if(x==y) return x;
    	for(i=Lg[dep[x]];i>=0;i--) if(fa[x][i]&&fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    ll Dis(int x,int y) {return dis[x]+dis[y]-2*dis[lca(x,y)];}
    void gr(int x,int y) {
    	int i;
    	siz[x]=1; fk[x]=0;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]&&vis[to[i]]==visc) {
    		gr(to[i],x); siz[x]+=siz[to[i]];
    		fk[x]=max(fk[x],siz[to[i]]);
    	}
    	fk[x]=max(fk[x],tot-siz[x]);
    	if(fk[x]<fk[rot]) rot=x;
    }
    void gd(int x,int y,int rt) {
    	int i;
    	all[rt]++;
    	F[rt][0].Ins(Dis(x,rt)-rr[x]);
    	F[rt][1].Ins(Dis(x,fb[rt])-rr[x]);
    	V[rt].push_back(x);
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]&&vis[to[i]]==visc) {
    		gd(to[i],x,rt);
    	}
    }
    void solve(int x) {
    	used[x]=1;
    	int i,al=tot;
    	V[x].clear();
    	all[x]=0;
    	F[x][0].rec(); F[x][1].rec();
    	gd(x,0,x);
    	for(i=head[x];i;i=nxt[i]) if(!used[to[i]]&&vis[to[i]]==visc) {
    		tot=siz[to[i]]; if(tot>siz[x]) tot=al-siz[x];
    		rot=0; gr(to[i],x); fb[rot]=x; solve(rot);
    	}
    }
    void update(int x) {
    	int t;
    	int kksk=0;
    	for(t=x;t;t=fb[t]) {
    		all[t]++;
    		F[t][0].Ins(Dis(x,t)-rr[x]);
    		F[t][1].Ins(Dis(x,fb[t])-rr[x]);
    		V[t].push_back(x);
    	}
    	for(t=x;fb[t];t=fb[t]) {
    		if(all[t]>all[fb[t]]*AL2) {
    			kksk=fb[t];
    		}
    	}
    	if(kksk) {
    		int p=kksk;
    		int i,lim=V[p].size(),ff=fb[p];
    		visc++;
    		for(i=0;i<lim;i++) {
    			vis[V[p][i]]=visc;
    			used[V[p][i]]=0;
    		}
    		rot=0;
    		tot=lim; 
    		gr(p,0);
    		fb[rot]=ff;
    		solve(rot);
    	}
    }
    int query(int x,int k) {
    	int t,re=0,lst=0;
    	ll len;
    	for(t=x;t;t=fb[t]) {
    		len=Dis(x,t);
    		re+=F[t][0].ask(F[t][0].root,k-len);
    		if(lst) re-=F[lst][1].ask(F[lst][1].root,k-len);
    		lst=t;
    	}
    	return re;
    }
    int main() {
    	fk[0]=1<<30;
    	rd(); n=rd();
    	int i,x,y,j;
    	rd(); rd(); rr[1]=rd();
    	for(i=1,Lg[0]=-1;i<=n;i++) Lg[i]=Lg[i>>1]+1;
    	dep[1]=1;
    	ll ans=0;
    	F[1][0].Ins(-rr[1]);
    	V[1].push_back(1); 
    	all[1]=1;
    	puts("0");
    	for(i=2;i<=n;i++) {
    		x=rd(); y=rd(); rr[i]=rd();
    		x^=(ans%1000000000);
    		dis[i]=dis[x]+y; dep[i]=dep[x]+1; fa[i][0]=x; fb[i]=x;
    		for(j=1;(1<<j)<=n;j++) fa[i][j]=fa[fa[i][j-1]][j-1];
    		add(x,i); add(i,x);
    		ans+=query(i,rr[i]);
    		printf("%lld
    ",ans);
    		update(i);
    	}
    }
    
    
  • 相关阅读:
    搭建Git本地服务器
    shutdown,init,halt,poweroff,reboot的区别和联系, pkill -kill -t tty7注销
    RHEL/CentOS/Fedora常用的 CentOS 5/6/7 yum 源(EPEL、Remi、RPMForge、RPMFusion, ius,163,sohu,阿里云)配置
    国内的一些开源镜像站汇总,EPEL源
    EditPlus 配置 Java & C/CPP 开发环境
    Nginx+Keepalived 做负载均衡器
    监控Nginx负载均衡器脚本
    Heartbeat+DRBD+NFS 构建高可用的文件系统
    数据库索引的作用和长处缺点
    【ThinkPHP学习】ThinkPHP自己主动转义存储富文本编辑器内容导致读取出错
  • 原文地址:https://www.cnblogs.com/suika/p/10164879.html
Copyright © 2020-2023  润新知