题目
容易发现题目中那个包含 1 1 1的连通块是提示你的,并不是来限制你的。
那么答案一定是 S S S中选择最大的若干个 w w w,剩下的 w w w的最大值 ≤ ∣ S ∣ \leq |S| ≤∣S∣。
设剩下的 w w w为集合 X X X
考虑一个调整的过程:
如果 ∣ S ∣ < max w ∈ X w |S| \lt \max_{w \in X} w ∣S∣<maxw∈Xw,则选出 max w ∈ X w \max_{w \in X} w maxw∈Xw从 X X X删去后加入 S S S。
如果 ∣ S ∣ > max w ∈ X w |S| \gt \max_{w\in X} w ∣S∣>maxw∈Xw并且 min w ∈ S w ≤ max w ∈ X w \min_{w \in S} w \leq \max_{w \in X} w minw∈Sw≤maxw∈Xw,则选出 min w ∈ S w \min_{w \in S} w minw∈Sw从 S S S删去后加入 X X X。
并且每次加点删点后只会有一次调整。(但是前提是你不是无脑的把所有点都加入 X X X,如果当前加入的点 w > max w ∈ X w w \gt \max_{w \in X} w w>maxw∈Xw的话还是要加入 S S S,否则就无法高效的维护 S S S和 X X X。)
注意这里我们一定要保证 max w ∈ X ≤ min w ∈ S \max_{w \in X} \leq \min_{w \in S} maxw∈X≤minw∈S。
那么就有一个很简单的 O ( q log 2 n ) O(q\log ^2n) O(qlog2n)做法:
线段树维护每个点的 w w w,和每个区间的 max w ∈ X w , min w ∈ S w \max_{w \in X} w , \min_{w \in S} w maxw∈Xw,minw∈Sw,然后每次调整即可。
注意到我们会有区间加一操作,如果在这次操作之后不满足 max w ∈ X ≤ min w ∈ S \max_{w \in X} \leq \min_{w \in S} maxw∈X≤minw∈S。
那么可以发现一定是(最多只有一个点)加一后达到了 ∣ S ∣ + 1 |S| + 1 ∣S∣+1,同时 S S S中还有值为 ∣ S ∣ |S| ∣S∣的元素。
那么只有一个点会违背规则,我们找出这样的一对点,他们分别在 X , S X,S X,S,然后将他们分别在 X , S X,S X,S删除后分别加入 S , X S,X S,X即可。
区间减一请读者自行思考。
使用 z k w zkw zkw线段树即可在 L O J LOJ LOJ上卡过此题。
但是本题还有 O ( n log n ) O(n\log n) O(nlogn)做法(没错就是速度最快的前几个那些动辄 7 K B 7KB 7KB的代码)
考虑树链剖分的链加,是难以做到小常数 O ( log n ) O(\log n) O(logn)的(不会真的有人想冲一百万的LCT吧?)
但是树状数组的单点修改 + + +子树求和可以轻松做到,只是我们不能求全局最小值了。
考虑题目给你的提示, S S S一定是包含根的连通块,所以在一条重链上所有的在 X X X中的点,只有最上面的点有资格作为 max w ∈ X w \max_{w \in X} w maxw∈Xw被操作。
S S S同理。
那么我们只维护每条重链上 X / S X/S X/S中深度最小/大的点的 w w w。(用 s e t set set)
在这些点被删除被加入的时候我们用树状数组 O ( log n ) O(\log n) O(logn)求出他们的 w w w。
在一条重链的某个前缀被整体加/减一的时候通过深度判断 X / S X/S X/S中深度最小/大的点的 w w w是否需要加/减一。
那么我们需要一个可以 O ( log n ) O(\log n) O(logn)插入, O ( 1 ) O(1) O(1)将一个点找到并且删除并且将他的值加一再插回去, O ( log n ) O(\log n) O(logn)求出最大/最小值。
注意到每次只会调整一次,所以求出最大值/最小值可以改为求出 w w w为某个值的点。
实际上直接写双向链表(就是对于每个值开一个链表连着所有值为这个值的点,每次删除可以直接用双向链表删除,记一下位置即可,我在实现的时候使用了 v e c t o r vector vector,插入删除都是 O ( 1 ) O(1) O(1)的)即可。
大数据结构写多了,我已经不会压行了怎么办啊。
A C C o d e \mathcal AC \ Code AC Code
#include
#define maxn 500005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
#define pb push_back
#define pii pair
#define vc vector
#define vi vc
#define Ct const
#define db double
using namespace std;
namespace IO{
char cb[1<<16] , *cs=cb,*ct=cb;
char getc(){ return cs == ct && (ct = (cs = cb) + fread(cb,1,1<<16,stdin),cs == ct) ? 0 : *cs++; }
template<class T>void read(T &res){
char ch;bool f=0;
for(;!isdigit(ch=getc());) if(ch=='-') f = 1;
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
(f) && (res = -res);
}
};
using IO :: getc;
using IO :: read;
int n,q,ans;
vi G[maxn];
int tp[maxn],son[maxn],sz[maxn],st[maxn],ed[maxn],pos[maxn],fa[maxn],tot;
struct cmp{
bool operator ()(Ct int &u,Ct int &v)Ct{ return st[u] < st[v]; }
};
set<int,cmp>P[maxn][2];
int W[maxn],B[maxn];
namespace BIT{
int tr[maxn];
void upd(int u,int v){ for(;u<=n;u+=u&-u) tr[u] += v; }
int qry(int u){ int r=0;for(;u;u-=u&-u) r+=tr[u]; return r; }
};
using BIT::upd;
using BIT::qry;
struct Chains{
vi G[maxn];
int loc[maxn];
void ins(int u,int w=-1){
if(w == -1) w = qry(ed[u]) - qry(st[u] - 1);
loc[u] = G[w].size();
G[w].push_back(u);
}
void del(int u,int w=-1){
if(w == -1) w = qry(ed[u]) - qry(st[u] - 1);
assert(!G[w].empty());
int t = G[w].back();
swap(loc[u] , loc[t]);
swap(G[w][loc[u]] , G[w][loc[t]]);
G[w].pop_back();
}
}C[2];
void INS(set<int,cmp>&u,Chains &v,int t){
if(u.empty()) return;
int p = (t ? *u.rbegin() : *u.begin());
v.ins(p,W[p]);
}
void DEL(set<int,cmp>&u,Chains &v,int t){
if(u.empty()) return;
int p = (t ? *u.rbegin() : *u.begin());
v.del(p,W[p]);
}
void dfs0(int u,int ff){
fa[u] = ff , sz[u] = 1;
for(int v:G[u]) if(v^ff)
dfs0(v,u) , sz[u] += sz[v] , (sz[v] > sz[son[u]]) && (son[u] = v);
}
void dfs1(int u,int ff){
pos[st[u] = ++tot] = u;
if(son[u]) tp[son[u]] = tp[u] , dfs1(son[u],u);
for(int v:G[u]) if(v^ff && v ^ son[u])
dfs1(tp[v] = v,u);
ed[u] = tot;
}
int main(){
freopen("1.in","r",stdin);
read(n);
rep(i,1,n-1){
int u,v;read(u) , read(v);
G[u].pb(v) , G[v].pb(u);
}
dfs0(1,0) , dfs1(tp[1] = 1,0);
read(q);
for(int op,u;q--;){
read(op) , read(u);
if(op == 1){
int w = qry(ed[u]) - qry(st[u] - 1);
if(w <= ans){
DEL(P[tp[u]][0],C[0],0);
W[u] = w , B[u] = 0;
P[tp[u]][0].insert(u);
INS(P[tp[u]][0],C[0],0);
}
else{
DEL(P[tp[u]][1],C[1],1);
W[u] = w , B[u] = 1 , ans++;
P[tp[u]][1].insert(u);
INS(P[tp[u]][1],C[1],1);
}
upd(st[u],1);
}
else{
if(!B[u]){
DEL(P[tp[u]][0],C[0],0);
P[tp[u]][0].erase(u);
if(!P[tp[u]][0].empty()){
int a = *P[tp[u]][0].begin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][0],C[0],0);
}
else{
DEL(P[tp[u]][1],C[1],1);
P[tp[u]][1].erase(u);
if(!P[tp[u]][1].empty()){
int a = *P[tp[u]][1].rbegin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][1],C[1],1);
ans --;
}
upd(st[u],-1);
}
for(;u;u=fa[tp[u]]){
int p = tp[u];
if(!P[p][0].empty() && st[*P[p][0].begin()] <= st[u]){
int v = *P[p][0].begin();
DEL(P[p][0],C[0],0);
W[v]+=(op == 1 ? 1 : -1);
INS(P[p][0],C[0],0);
}
if(!P[p][1].empty() && st[*P[p][1].rbegin()] <= st[u]){
int v = *P[p][1].rbegin();
DEL(P[p][1],C[1],1);
W[v]+=(op == 1 ? 1 : -1);
INS(P[p][1],C[1],1);
}
}
if(op == 1){
if(!C[0].G[ans+1].empty() && !C[1].G[ans].empty()){
int u = C[0].G[ans+1].back() , v = C[1].G[ans].back();
DEL(P[tp[u]][0],C[0],0);
DEL(P[tp[u]][1],C[1],1);
if(tp[v] ^ tp[u])
DEL(P[tp[v]][1],C[1],1),
DEL(P[tp[v]][0],C[0],0);
P[tp[u]][0].erase(u);
P[tp[u]][1].insert(u);
P[tp[v]][1].erase(v);
P[tp[v]][0].insert(v);
int a = u;
if(!P[tp[u]][0].empty()){
a = *P[tp[u]][0].begin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
if(!P[tp[v]][1].empty()){
a = *P[tp[v]][1].rbegin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][0],C[0],0);
INS(P[tp[u]][1],C[1],1);
if(tp[u] ^ tp[v])
INS(P[tp[v]][1],C[1],1),
INS(P[tp[v]][0],C[0],0);
swap(B[u],B[v]);
}
if(!C[0].G[ans+1].empty()){
int u = C[0].G[ans+1].back();
ans++;
DEL(P[tp[u]][0],C[0],0);
DEL(P[tp[u]][1],C[1],1);
P[tp[u]][0].erase(u);
P[tp[u]][1].insert(u);
if(!P[tp[u]][0].empty()){
int a = *P[tp[u]][0].begin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][0],C[0],0);
INS(P[tp[u]][1],C[1],1);
B[u] = 1;
}
else if(C[0].G[ans].empty()){
if(ans && !C[1].G[ans-1].empty()) {
int u = C[1].G[ans-1].back();
ans--;
DEL(P[tp[u]][0],C[0],0);
DEL(P[tp[u]][1],C[1],1);
P[tp[u]][1].erase(u);
P[tp[u]][0].insert(u);
if(!P[tp[u]][1].empty()){
int a = *P[tp[u]][1].rbegin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][0],C[0],0);
INS(P[tp[u]][1],C[1],1);
B[u] = 0;
}
}
}
else{
if(ans && !C[0].G[ans].empty() && !C[1].G[ans-1].empty()){
int u = C[0].G[ans].back() , v = C[1].G[ans-1].back();
DEL(P[tp[u]][0],C[0],0);
DEL(P[tp[u]][1],C[1],1);
if(tp[u] ^ tp[v])
DEL(P[tp[v]][1],C[1],1),
DEL(P[tp[v]][0],C[0],0);
P[tp[u]][0].erase(u);
P[tp[u]][1].insert(u);
P[tp[v]][1].erase(v);
P[tp[v]][0].insert(v);
int a = u;
if(!P[tp[u]][0].empty()){
a = *P[tp[u]][0].begin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
if(!P[tp[v]][1].empty()){
a = *P[tp[v]][1].rbegin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][0],C[0],0);
INS(P[tp[u]][1],C[1],1);
if(tp[u] ^ tp[v])
INS(P[tp[v]][1],C[1],1),
INS(P[tp[v]][0],C[0],0);
swap(B[u],B[v]);
}
if(!C[0].G[ans+1].empty()){
int u = C[0].G[ans+1].back();
ans++;
DEL(P[tp[u]][0],C[0],0);
DEL(P[tp[u]][1],C[1],1);
P[tp[u]][0].erase(u);
P[tp[u]][1].insert(u);
if(!P[tp[u]][0].empty()){
int a = *P[tp[u]][0].begin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][0],C[0],0);
INS(P[tp[u]][1],C[1],1);
B[u] = 1;
}
else if(C[0].G[ans].empty()){
if(ans && !C[1].G[ans-1].empty()) {
int u = C[1].G[ans-1].back();
ans--;
DEL(P[tp[u]][0],C[0],0);
DEL(P[tp[u]][1],C[1],1);
P[tp[u]][1].erase(u);
P[tp[u]][0].insert(u);
if(!P[tp[u]][1].empty()){
int a = *P[tp[u]][1].rbegin();
W[a] = qry(ed[a]) - qry(st[a] - 1);
}
INS(P[tp[u]][0],C[0],0);
INS(P[tp[u]][1],C[1],1);
B[u] = 0;
}
}
}
printf("%d\n",ans);
}
}