标签:har 时间复杂度 tps 如何 多少 集合 add class 状态
线段树合并简单题,贪心神题!
题意简述:给定一棵树,每个点有权值\(w_i\),要求你选择一个最大的点集(不要求联通),使得若\(u是v的祖先\),则\(w_u \leq w_v\).
/*[FJOI2018]领导集团问题*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
bool fuck = 0;
int read(){
char c = getchar();
int x = 0;
while(c < ‘0‘ || c > ‘9‘) c = getchar();
while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - 48,c = getchar();
return x;
}
const int N = 4e5 + 10;
struct SegmentTree{
int lc,rc;
int mx,add;
}t[N<<5];
int cnt = 0;
void pushup(int p){
t[p].mx = max(t[t[p].lc].mx,t[t[p].rc].mx);
}
void pushadd(int p,int v){
t[p].mx += v;
t[p].add += v;
}
void pushdown(int p){
if(t[p].add){
int v = t[p].add;
if(t[p].lc) pushadd(t[p].lc,v);
if(t[p].rc) pushadd(t[p].rc,v);
t[p].add = 0;
}
}
void ins(int &p,int l,int r,int pos,int v){
if(!p) p = ++cnt;
if(l == r){
t[p].mx = max(v,t[p].mx);
return;
}
pushdown(p);
int mid = (l + r) >> 1;
if(pos <= mid) ins(t[p].lc,l,mid,pos,v);
else ins(t[p].rc,mid+1,r,pos,v);
pushup(p);
}
int query(int p,int l,int r,int a,int b){
if(!p || a > b) return 0;
if(a <= l && b >= r) return t[p].mx;
int mid = (l + r) >> 1;
pushdown(p);
int ans = 0;
if(a <= mid) ans = max(ans,query(t[p].lc,l,mid,a,b));
if(b > mid) ans = max(ans,query(t[p].rc,mid+1,r,a,b));
return ans;
}
int merge(int u,int v,int l,int r,int mx1,int mx2){
if(!u || !v){
if(!u && !v) return 0;
if(!u){
// t[v].mx = (mx1 + t[v].mx);
pushadd(v,mx1);
return v;
}
if(!v){
// t[u].mx = (mx2 + t[u].mx);
pushadd(u,mx2);
return u;
}
}
if(l == r){
mx2 = max(mx2,t[v].mx);mx1 = max(mx1,t[u].mx);
int Mx = max(t[u].mx + mx2,t[v].mx + mx1);
t[u].mx = Mx;
return u;
}
pushdown(u);pushdown(v);
int mid = (l + r) >> 1;
t[u].lc = merge(t[u].lc,t[v].lc,l,mid,max(mx1,t[t[u].rc].mx),max(mx2,t[t[v].rc].mx));
t[u].rc = merge(t[u].rc,t[v].rc,mid+1,r,mx1,mx2);
pushup(u);
return u;
}
int tmp[N],w[N],n,rt[N],k;
struct Edge{
int nxt,point;
}edge[N<<1];int head[N],tot;
void dfs(int u){
int Pyy = 1;
for(int i = head[u]; i ; i = edge[i].nxt){
int v = edge[i].point;
dfs(v);
int S1 = 0,S2 = 0;
Pyy += query(rt[v],1,k,w[u],k);
rt[u] = merge(rt[u],rt[v],1,k,S1,S2);
}
ins(rt[u],1,k,w[u],Pyy);
}
void add_edge(int u,int v){
edge[++tot].nxt = head[u];
edge[tot].point = v;
head[u] = tot;
}
int main(){
// freopen("boss10.in","r",stdin);
n = read();
for(int i = 1; i <= n; ++i) w[i] = read(),tmp[i] = w[i];
sort(tmp+1,tmp+n+1);
k = unique(tmp+1,tmp+n+1) - tmp - 1;
for(int i = 1; i <= n ; ++i) w[i] = lower_bound(tmp+1,tmp+k+1,w[i]) - tmp;
for(int i = 2; i <= n; ++i){
int fa = read();
add_edge(fa,i);
}
dfs(1);
printf("%d\n",t[rt[1]].mx);
return 0;
}
标签:har 时间复杂度 tps 如何 多少 集合 add class 状态
原文地址:https://www.cnblogs.com/y-dove/p/14526883.html