平衡树好题啊
现在暂时还不知道用普通线段树该咋做。。。。
刚刚做完 二逼平衡树,感觉自己的 \(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();}