【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

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。