題目
正解
老勢能分析了。
聯通塊個數等於點數減邊數。
用個數據結構維護權值大於等於某個值的點數和邊數有多少個。邊的權值定義爲兩邊連着的點的點權的最小值。
點權的維護隨便搞,重點是邊權的維護。
隨便定一個根,對於每個點用個set
維護有多少個兒子的權值大於它。
在權值變大的時候,對於父親邊就直接做,對於兒子邊,將原來權值大於它,現在權值小於等於它的兒子暴力修改。
勢能分析,設勢能爲每個點的兒子大於它的個數。每次詢問,勢能頂多加一。
所以時間複雜度爲,後面的這個是數據結構的時間複雜度。
代碼
實現的時候注意細節,比如什麼小於和小於等於之類的。
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define N 500010
#define MX 1000000
int input(){
char ch=getchar();
while (ch<'0' || ch>'9')
ch=getchar();
int x=0;
do{
x=x*10+ch-'0';
ch=getchar();
}
while ('0'<=ch && ch<='9');
return x;
}
int n;
int h[N];
struct EDGE{
int to;
EDGE *las;
} e[N*2];
int ne;
EDGE *last[N];
int fa[N];
void init(int x){
static int q[N];
int head=1,tail=1;
q[1]=x;
while (head<=tail){
int x=q[head++];
for (EDGE *ei=last[x];ei;ei=ei->las)
if (ei->to!=fa[x]){
fa[ei->to]=x;
q[++tail]=ei->to;
}
}
}
int td[MX+10],te[MX+10];
void add(int x,int c,int t[]){
for (;x<=MX;x+=x&-x)
t[x]+=c;
}
int query(int x,int t[]){
int r=0;
for (;x;x-=x&-x)
r+=t[x];
return r;
}
struct Num{int x,s;};
bool operator<(Num a,Num b){return a.s<b.s || a.s==b.s && a.x<b.x;}
multiset<Num> s[N];
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n=input();
int Q=input();
for (int i=1;i<=n;++i){
h[i]=input();
add(h[i],1,td);
}
for (int i=1;i<n;++i){
int u=input(),v=input();
e[ne]={v,last[u]};
last[u]=e+ne++;
e[ne]={u,last[v]};
last[v]=e+ne++;
}
init(1);
for (int i=2;i<=n;++i){
// printf("%d\n",min(h[i],h[fa[i]]));
add(min(h[i],h[fa[i]]),1,te);
if (h[i]>h[fa[i]])
s[fa[i]].insert({i,h[i]});
}
// printf("\n");
while (Q--){
int op=input();
if (op==1){
int x=input(),y=input();
add(h[x],-1,td),add(y,1,td);
auto p=s[x].begin();
add(h[x],-s[x].size(),te);
for (auto q=p;p!=s[x].end() && h[p->x]<=y;q=p,++p,s[x].erase(q))
add(h[p->x],1,te);
add(y,s[x].size(),te);
if (h[x]<=h[fa[x]]){
add(h[x],-1,te);
if (y>h[fa[x]]){
add(h[fa[x]],1,te);
h[x]=y;
s[fa[x]].insert({x,h[x]});
}
else{
add(y,1,te);
h[x]=y;
}
}
else{
s[fa[x]].erase({x,h[x]});
h[x]=y;
s[fa[x]].insert({x,h[x]});
}
}
else{
int y=input();
printf("%d\n",(query(MX,td)-query(y-1,td))-(query(MX,te)-query(y-1,te)));
}
}
return 0;
}