【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)
第一种做法(时间太感人):
这题我真的逗了,调了一下午,疯狂造数据,始终找不到错。
后来发现自己sb了,更新那里没有打id,直接套上u了。我。。。。
调了一下午啊!一下午的时光啊!本来说好中午A掉去学习第二种做法,噗
好吧,现在第一种做法是hld+seg+bst+二分,常数巨大,log^4级别,目前只会这种。
树剖后仍然用线段树维护dfs序区间,然后在每个区间建一颗平衡树,我用treap,(这题找最大啊,,,囧,并且要注意,这里的rank是比他大的数量,so,我们在二分时判断要判断一个范围,即要加上它重叠的数量,这点自己调试的时候找出来了)
我们将路径放进一个池子里,然后累计排名就行了。
时间很感人啊。
(希望以后不要犯这种sb错了,唉,太逗。)
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; #define dbg(x) cout << #x << "=" << x << endl #define read(x) x=getint() #define rdm(u) for(int i=ihead[u]; i; i=e[i].next) #define lc x<<1 #define rc x<<1|1 #define lson l, m, lc #define rson m+1, r, rc #define MID (l+r)>>1 inline const int getint() { char c=getchar(); int ret=0, k=1; for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) ret=ret*10+c-‘0‘; return k*ret; } const int N=80010, oo=~0u>>1; int n, q, ihead[N], brr[N], arr[N], cnt, bak, flg, L, R, same; int fa[N], top[N], son[N], dep[N], sz[N], id[N], tot, num; struct Ed { int to, next; }e[N<<1]; inline void add(const int &u, const int &v) { e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; } struct node* null; struct node { node* ch[2]; int wei, key, sz, cnt; void pushup() { sz=ch[0]->sz+ch[1]->sz+cnt; } node(int _w=0, int _sz=1, int _cnt=1) : key(_w), sz(_sz), cnt(_cnt) { ch[0]=ch[1]=null; wei=rand(); } }*root[N*50], *nd[N*50]; inline void rot(node* &x, const bool d) { node* t=x->ch[!d]; x->ch[!d]=t->ch[d]; t->ch[d]=x; x->pushup(); t->pushup(); x=t; } void insert(node* &x, const int &key) { if(x==null) { x=new node(key); return; } if(key==x->key) { ++x->cnt; ++x->sz; return; } bool d=key>x->key; insert(x->ch[d], key); if(x->wei>x->ch[d]->wei) rot(x, !d); x->pushup(); } void remove(node* &x, const int &key) { if(x==null) return; bool d=key>x->key; if(key==x->key) { if(x->cnt>1) { --x->cnt; --x->sz; return; } d=x->ch[0]->wei > x->ch[1]->wei; if(x->ch[d]==null) { delete x; x=null; return; } rot(x, !d); remove(x->ch[!d], key); } else remove(x->ch[d], key); x->pushup(); } inline int rank(node* x, const int &key) { int ret=0, s; while(x!=null) { s=x->ch[1]->sz + x->cnt; if(key==x->key) same+=x->cnt; if(key<x->key) ret+=s, x=x->ch[0]; else x=x->ch[1]; } return ret; } void build(const int &l, const int &r, const int &x) { if(l==r) { root[x]=new node(brr[l]); return; } int m=MID; build(lson); build(rson); root[x]=new node(brr[l]); for(int i=l+1; i<=r; ++i) insert(root[x], brr[i]); } void update(const int &l, const int &r, const int &x) { if(l==r) { remove(root[x], bak); insert(root[x], flg); return; } int m=MID; remove(root[x], bak); insert(root[x], flg); if(L<=m) update(lson); if(m<R) update(rson); } void query(const int &l, const int &r, const int &x) { if(L<=l && r<=R) { nd[++num]=root[x]; return; } int m=MID; if(L<=m) query(lson); if(m<R) query(rson); } void dfs1(const int &u) { sz[u]=1; int v; rdm(u) if(fa[u]!=(v=e[i].to)) { fa[v]=u; dep[v]=dep[u]+1; dfs1(v); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; } } void dfs2(const int &u, const int &tp) { id[u]=++tot; top[u]=tp; brr[tot]=arr[u]; if(son[u]) dfs2(son[u], tp); rdm(u) if(fa[u]!=e[i].to && son[u]!=e[i].to) dfs2(e[i].to, e[i].to); } void getrange(int x, int y) { num=0; int fx=top[x], fy=top[y]; while(fx!=fy) { if(dep[fx]<dep[fy]) { swap(x, y); swap(fx, fy); } L=id[fx], R=id[x]; query(1, n, 1); x=fa[fx]; fx=top[x]; } if(dep[x]>dep[y]) swap(x, y); L=id[x], R=id[y]; query(1, n, 1); } int getrank(const int &key) { int ret=0; same=0; for(int i=1; i<=num; ++i) ret+=rank(nd[i], key); return ret; } int getans(int x, int y, int k) { getrange(x, y); node* rt; int l=oo+1, r=oo, s=0; for(int i=1; i<=num; ++i) s+=nd[i]->sz; if(s<k) return l; for(int i=1; i<=num; ++i) { rt=nd[i]; while(rt!=null) { if(rt->key<l) { rt=rt->ch[1]; continue; } if(rt->key>r) { rt=rt->ch[0]; continue; } s=getrank(rt->key); if(s+1<=k && k<=s+same) return rt->key; //这里要注意 if(s+same>k) { l=rt->key; rt=rt->ch[1]; } else { r=rt->key; rt=rt->ch[0]; } } } return l; } int main() { null=new node(0, 0, 0); null->wei=oo; read(n); read(q); int u, v, k, ans; for(int i=1; i<=n; ++i) read(arr[i]); for(int i=1; i<n; ++i) { read(u); read(v); add(u, v); } dfs1(1); dfs2(1, 1); build(1, n, 1); while(q--) { read(k); read(u); read(v); if(!k) { bak=arr[u]; flg=arr[u]=v; L=R=id[u]; update(1, n, 1); } else { ans=getans(u, v, k); if(ans==oo+1) puts("invalid request!"); else printf("%d\n", ans); } } return 0; }
【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树),古老的榕树,5-wow.com
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。