[noip6]模板

平衡树好题啊

现在暂时还不知道用普通线段树该咋做。。。。

刚刚做完 二逼平衡树,感觉自己的 \(splay\) 水平有了很大很大的长进,然鹅。。。。

这题又给我当头一棒。。。。

然后就一下午出去了但总算也是调出来了。。。

整挺好

做这个题目的时候又想到当时那一场考试的时候,考试结束之后本以为自己在考试的时候一共四个题目,看错了三个,结果。。。。

\(\huge{\text{这个也没看对。。。}}\)

我太 \(naive\) 了,做 \(fAKe\)

所以我立下毒誓,以后如果题目还没有看10遍就开始码我就随刘子康的姓。。。

不扯淡了


这个题目其实和二逼平衡树还是很像很像的,都是开很多的 \(splay\) 而不是仅仅一棵,然后再进行统计或者是合并操作。。。

这个题目所要维护的东西还是比较新颖的,将时间作为排序的标准值。。。

然后就可以对于每一个点的信息进行插入,color time ,还有一些之前 \(splay\) 套路的一些信息。

然后就是用 time 进行排序。。。

就这???

你维护试试,包准没入门

最后进行一遍 \(dfs\),然后进行启发式合并就行了。。。。

然后就是 \(code\)

#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define debug cout<<"debug"<<endl
#define freopen eat2 = freopen
#define scanf eat1 = scanf
namespace xin_io
{
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	#define scanf eat1 = scanf 
	#define freopen eat2 = freopen
	char buf[1<<20],*p1 = buf,*p2 = buf;FILE *eat2;
	inline void openfile() {freopen("t.txt","r",stdin);} inline void outfile(){freopen("o.txt","w",stdout);}
	inline int get()
	{
		int s = 0,f = 1;register char ch = gc();
		while(!isdigit(ch))
		{if(ch == '-') f = -1;ch = gc();}
		while(isdigit(ch))
		{s = s * 10 + ch - '0';ch = gc();}return s * f;
	}
}
using namespace xin_io; int eat1;
static const int maxn = 2e6+10,mod = 1e6;
namespace xin
{
	class xin_splay{public:int cnt,col,tim,ch[2],val,fa,size;}t[maxn];
	class xin_edge{public:int next,ver;}edge[maxn]; int head[maxn],zhi = 0;
	int tot,ret;
	class xin_splay_tree
	{
		private:
			#define up(x) t[x].size = t[t[x].ch[1]].size + t[t[x].ch[0]].size + 1,t[x].cnt = t[t[x].ch[1]].cnt + t[t[x].ch[0]].cnt + t[x].val
 		public:
			int root;		  //to distinguish different splay trees
			map<int,int>vis;  //to record the tim of color
			inline int size() {return t[root].size;}
			inline void rotate(int x)
			{
				register int y = t[x].fa,z = t[y].fa;
				register int ki = t[y].ch[1] == x;
				t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z;
				t[y].ch[ki] = t[x].ch[ki xor 1]; t[t[x].ch[ki xor 1]].fa = y;
				t[x].ch[ki xor 1] = y; t[y].fa = x;
				up(y);	up(x);
			}//checked  	
			inline void splay(int x,int goal)
			{
				while(t[x].fa != goal)
				{
					register int y = t[x].fa, z = t[y].fa;
					if(z != goal)
						(t[z].ch[0] == y) xor (t[y].ch[0] == x) ? rotate(x) : rotate(y);
					rotate(x);
				}
				up(x);
				root = x;
			}//checked
			inline void insert(int tim,int col,int val)
			{
				register int now = root,fa = 0;
				while(now and tim != t[now].tim) fa = now,now = t[now].ch[tim > t[now].tim];
				now = ++tot;
				if(fa) t[fa].ch[tim > t[fa].tim] = now;
				t[now].cnt = t[now].val = val;
				t[now].fa = fa; t[now].tim = tim; t[now].size = 1; t[now].col = col;
				splay(now,0);
			}//checked

			void change(int tim)
			{
				register int now = root;
				while(now and t[now].tim != tim)
					now = t[now].ch[tim > t[now].tim];
				if(now) t[now].val = 0;
				splay(now,0);
			}//checked
			inline bool judge(int tim,int col)
			{
				if(!vis[col]) {vis[col] = tim; return true;}
				else if(vis[col] > tim) {change(vis[col]);vis[col] = tim; return true;}
				else return false;
			}	//checked
			int findx(int x,int lim)
			{
				if(!x) return 0;
				if(t[t[x].ch[0]].size >= lim) findx(t[x].ch[0],lim);
				else if(t[t[x].ch[0]].size + 1 >= lim) return  ret + t[t[x].ch[0]].cnt + t[x].val;
				else ret += t[t[x].ch[0]].cnt + t[x].val,findx(t[x].ch[1],lim -t[t[x].ch[0]].size - 1);
			}//checked
			int findval(int lim)
			{
				ret = 0;
				if(!lim) return 0;
				if(lim >= t[root].size) return t[root].cnt;
				int ret = findx(root,lim); return ret;
			}//checked
	}a[maxn];
	int n,m,ans[maxn],k[maxn],rec[maxn]; //rec is to make a node for each splay tree
	inline void add(int x,int y) {edge[++zhi].ver = y;edge[zhi].next = head[x]; head[x] = zhi;}
	int now;
	inline void make(int x)
	{
		if(!x) return ;
		make(t[x].ch[0]);
		a[now].insert(t[x].tim,t[x].col,a[now].judge(t[x].tim,t[x].col));
		make(t[x].ch[1]);
	}
	void dfs(int x,int fa)
	{
		for(register int i=head[x];i;i=edge[i].next)
		{
			register int y = edge[i].ver;
			if(fa == y) continue;
			dfs(y,x);
			if(a[rec[x]].size() < a[rec[y]].size())
			{
			//	cout<<x<<endl;
				now = rec[y];
				make(a[rec[x]].root);
				rec[x] = now;
			}
			else 
			{
				now = rec[x];
				make(a[rec[y]].root);
			//	rec[y] = now;
			}
		}
		ans[x] = a[rec[x]].findval(k[x]);
	}
	inline double time() {return (double)clock()/(double)(CLOCKS_PER_SEC);}
	inline short main()
	{
	#ifndef ONLINE_JUDGE
		openfile();
	#endif
		n = get();
		for(register int i=1;i<=n-1;++i)
		{
			register int x = get(),y = get();
			add(x,y); add(y,x);
		}
		for(register int i=1;i<=n;++i) k[i] = get(),rec[i] = i;
		m = get();// time();
		for(register int i=1;i<=m;++i)
		{
			register int x = get(),col = get();
			a[rec[x]].insert(i,col,a[rec[x]].judge(i,col));
		}
		dfs(1,0);
		int q = get();
		while(q--)
			printf("%d\n",ans[get()]);
		return 0;
	}
}
signed main() {return xin::main();}

posted @ 2021-06-13 18:37  NP2Z  阅读(37)  评论(0编辑  收藏  举报