绝版题

xiaoxiao2021-02-27  371

题目描述

所谓的考试,就一定有一道绝版题使得男人沉默女人流泪,而不有理有据的绝版题怎么称得上绝版呢? 火车国一开始只有一座城市,也就是1号城市。不过火车国的领土是在不断变化的,经常会新添加一个城市,那么小火车就会用一条铁路把它和某个老城市连接起来。 偶尔火车国会发生自然灾害,那么小火车就得找到一个合适的城市指挥赈灾,这个城市满足所有城市到其距离乘以城市人口的和最小,如果有不止一个最小的城市时小火车会选择距离1号城市最近的。 当然火车国人口也是不断变化的,也就是说有时候某个城市的人口会改变。现在小火车请你告诉他每次指挥赈灾应该选择的城市。

数据结构

用LCT来维护会动的树。 怎么求带权重心呢? 从1开始。 先看看是否要往1所在重链方向走,否则找到轻边中子树权值和最大的,看看是否往那边走。 在重链方向上走可以在splay上二分。 轻边子树权值和最大通过LCT+set维护虚边信息。 每次找到带权重心后access,这样复杂度就对了!因为虚实切换次数均摊n log n。

#include<cstdio> #include<algorithm> #include<set> #define fo(i,a,b) for(i=a;i<=b;i++) #define max(a,b) (a>b?a:b) using namespace std; typedef long long ll; const int maxn=300000+10; struct dong{ int x; ll y; friend bool operator <(dong a,dong b){ return a.y<b.y||a.y==b.y&&a.x<b.x; } } zlt; set<dong> s[maxn]; set<dong>::iterator it; ll mx[maxn],key[maxn],ad[maxn]; int a[maxn],size[maxn]; int father[maxn],tree[maxn][2],pp[maxn],sta[maxn]; int i,j,k,l,t,n,m,tot,top,ans,lastans,nans,de; ll sum; bool czy,gjx; int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } int pd(int x){ return tree[father[x]][1]==x; } void update(int x){ mx[x]=key[x]; if (tree[x][0]) mx[x]=max(mx[x],mx[tree[x][0]]); if (tree[x][1]) mx[x]=max(mx[x],mx[tree[x][1]]); size[x]=size[tree[x][0]]+size[tree[x][1]]+1; } void rotate(int x){ int y=father[x],z=pd(x); father[x]=father[y]; if (father[y]) tree[father[y]][pd(y)]=x; tree[y][z]=tree[x][1-z]; if (tree[x][1-z]) father[tree[x][1-z]]=y; tree[x][1-z]=y; father[y]=x; if (pp[y]) pp[x]=pp[y],pp[y]=0; update(y); update(x); } void mark(int x,int v){ if (!x) return; key[x]+=(ll)v; mx[x]+=(ll)v; ad[x]+=(ll)v; } void down(int x){ if (ad[x]){ mark(tree[x][0],ad[x]); mark(tree[x][1],ad[x]); ad[x]=0; } } void remove(int x,int y){ top=0; while (x!=y){ sta[++top]=x; x=father[x]; } while (top) down(sta[top--]); } void splay(int x,int y){ remove(x,y); while (father[x]!=y){ if (father[father[x]]!=y) if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x); rotate(x); } } ll getkey(int x){ splay(x,0); return key[x]; } void real_empty(int x,int y){ splay(y,0); splay(x,y); tree[y][1]=0; update(y); father[x]=0; pp[x]=y; zlt.x=x;zlt.y=getkey(x); s[y].insert(zlt); } void empty_real(int x,int y){ splay(y,0); splay(x,0); tree[y][1]=x; update(y); father[x]=y; pp[x]=0; zlt.x=x;zlt.y=getkey(x); s[y].erase(s[y].find(zlt)); } void access(int x){ int y,z; splay(x,0); z=tree[x][1]; if (z){ while (tree[z][0]){ down(z); z=tree[z][0]; } splay(z,x); real_empty(z,x); } while (pp[x]){ y=pp[x]; splay(y,0); z=tree[y][1]; if (z){ while (tree[z][0]){ down(z); z=tree[z][0]; } splay(z,y); real_empty(z,y); } while (tree[x][0]){ down(x); x=tree[x][0]; } splay(x,0); empty_real(x,y); splay(x,0); } } void link(int x,int y){ pp[y]=x; zlt.x=y;zlt.y=getkey(y); s[x].insert(zlt); } int find(int x){ down(x); if (mx[tree[x][1]]>sum/2) return find(tree[x][1]); if (key[x]>sum/2) return x; else return find(tree[x][0]); } int main(){ freopen("jueban.in","r",stdin);freopen("jueban.out","w",stdout); mx[0]=-1000000000000000; czy=1; m=read();a[tot=1]=size[1]=read(); key[1]=mx[1]=sum=a[1]; while (m--){ t=read(); if (t==1){ j=read();k=read(); if (czy){ j^=lastans;k^=lastans; } ++tot; size[tot]=1; a[tot]=k; link(j,tot); access(tot); splay(tot,0); sum+=(ll)k; mark(tot,k); } else if (t==2){ j=read();k=read(); if (czy){ j^=lastans;k^=lastans; } access(j); splay(j,0); k=k-a[j]; a[j]+=k; sum+=(ll)k; mark(j,k); } else{ ans=1; while (1){ splay(ans,0); if (tree[ans][1]){ t=tree[ans][1]; while (tree[t][0]){ down(t); t=tree[t][0]; } splay(t,0); if (key[t]>sum/2){ splay(ans,0); ans=find(tree[ans][1]); continue; } } it=s[ans].end(); if (it==s[ans].begin()) break; it--; zlt=*it; if (zlt.y<=sum/2) break; ans=zlt.x; } access(ans); printf("%d\n",ans); lastans=ans; } //printf("%d\n",m); } }
转载请注明原文地址: https://www.6miu.com/read-4591.html

最新回复(0)