此题博主使用树状数组套树链剖分的做法 , 严格来说空间是不够用的 , 但是由于此题存在一个骑士的力量值的分部问题 , 如果边修改边开内存是完全没问题的。
骑士力量当作权值放在最外层用树状数组处理 , 然后树链剖分线段树记录此处是否有骑士。 每次询问用树状数组找第K大就可以啦。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>
using namespace std;
const int maxn = 4e4+1e2;
const int maxv = 1e3+1e2;
const int speSize = 2000000;
__inline int re() {
int n = 0, ch = getchar(); bool flag = false;
while(!isdigit(ch)) flag |= ch == '-', ch = getchar();
while(isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
return flag ? -n : n;
}
struct node
{
node* l , *r;
short sum;
node(){ sum=0; }
void maintain() { sum = l->sum + r->sum; }
};
node* null = new node();
node pool[speSize]; int CNT;
node* newNode()
{
pool[CNT].l = pool[CNT].r = null;
return &pool[CNT++];
}
int query(node* o , int l , int r , int L , int R)
{
if(o == null) return 0;
if(L <= l && r <= R) return o->sum;
else
{
int mid = (l+r)/2 , res=0;
if(L <= mid) res+= query(o->l, l, mid, L, R);
if(R > mid) res+= query(o->r, mid+1, r, L, R);
return res;
}
}
void modify(node* &o , int l , int r , int p , int v)
{
if(o == null) o = newNode();
if(l==r) o->sum += v;
else
{
int mid = (l+r)/2;
if(p <= mid) modify(o->l, l, mid, p, v);
else modify(o->r, mid+1 , r, p, v);
o->maintain();
}
}
int n , m , Q , K;
vector<int> g[maxn];
int fa[maxn] , Size[maxn] , dep[maxn];
void dfs(int u)
{
Size[u] = 1;
dep[u] = dep[fa[u]]+1;
for(int i=0;i<g[u].size();i++)
{
int t = g[u][i];
if(t == fa[u]) continue;
fa[t] = u;
dfs(t);
Size[u] += Size[t];
}
}
int id[maxn] , bl[maxn] , s[maxn] , dfsCnt;
void dfs(int u , int num)
{
id[u] = ++dfsCnt;
bl[u] = num;
s[num]++;
int mx = 0 , w;
for(int i=0;i<g[u].size();i++)
{
int t = g[u][i];
if(t == fa[u]) continue;
if(mx < Size[t]) mx = Size[t] , w = t;
}
if(mx) dfs(w, num);
for(int i=0;i<g[u].size();i++)
{
int t = g[u][i];
if(t == fa[u] || t==w) continue;
dfs(t, t);
}
}
node* build(int l , int r)
{
node* res = newNode();
if(l!=r)
{
int mid = (l+r)/2;
res->l = build(l, mid);
res->r = build(mid+1, r);
}
return res;
}
const int mx = 1000;
node* root[maxv];
__inline int lowbit(int x) { return x&-x; }
void modify(int v, int p , int a)
{
for(int i=v;i<=mx;i+=lowbit(i))
modify(root[i], 1, n, p, a);
}
int query(node* o , int x , int y)
{
int f , res=0;
while(bl[x] != bl[y])
{
if(dep[bl[x]] > dep[bl[y]]) swap(x, y);
f = bl[y];
res+= query(o, 1, n, id[f], id[y]);
y = fa[f];
}
// if(x!=y)
{
if(dep[x] > dep[y]) swap(x, y);
res+= query(o, 1, n, id[x], id[y]);
}
return res;
}
int hehe(int v , int x , int y)
{
int res =0 ;
for(int i=v;i;i-=lowbit(i)) res+= query(root[i], x, y);
return res;
}
int findK(int k , int x , int y)
{
int res = 0 , now;
for(int i=512;i;i/=2)
{
if(res+i>mx) continue;
if((now = query(root[res+i], x, y)) >= k) continue;
k -= now;
res+=i;
}
return res+1;
}
int pl[maxn] , fi[maxn] , q[maxn];
int main(int argc, char *argv[]) {
// freopen("input", "r", stdin);
cin>>n;
int a , b;
for(int i=1;i<n;i++)
{
a = re(); b = re();
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1);
dfs(1, 1);
for(int i=1;i<=mx;i++) root[i] = null;
cin>>m;
for(int i=1;i<=m;i++)
{
fi[i] = re(); pl[i] = re();
fi[i] = mx+1-fi[i];
modify(fi[i], id[pl[i]], 1);
}
cin>>Q>>K;
int t , x , y , k;
while(Q--)
{
t = re(); x = re(); y = re();
if(t==2)
{
modify(fi[x], id[pl[x]], -1);
pl[x] = y;
modify(fi[x], id[pl[x]], 1);
}
else if(t==3)
{
modify(fi[x], id[pl[x]], -1);
fi[x] = mx+1-y;
modify(fi[x], id[pl[x]], 1);
}
else
{
k = 0;
do
{
if((q[k] = findK(k+1, x, y))==mx+1) break;
}while(++k<K);
if(!k) puts("-1");
else for(int j=0;j<k;j++) printf("%d%s" , mx+1-q[j] , j==k-1?" \n":" ");
}
}
return 0;
}