《数据结构汇总》

闭关。

 

P2234 [HNOI2002]营业额统计

直接splay插入就可以了。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
const int N = 2e5 + 5;
const int M = 2e4 + 5;
const double eps = 1e-10;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e8
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read() {
    int f = 1;int x = 0;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
inline long long ADD(long long x,long long y) {return (x + y) % Mod;}
inline long long DEC(long long x,long long y) {return (x - y + Mod) % Mod;}
inline long long MUL(long long x,long long y) {return x * y % Mod;}


int f[N],cnt[N],value[N],sons[N][2],sz[N],allsz,rt;

inline bool get_which(int x) {return sons[f[x]][1] == x;}
inline void update(int x) {
    if(x) {
        sz[x] = cnt[x];
        if(sons[x][0]) sz[x] += sz[sons[x][0]];
        if(sons[x][1]) sz[x] += sz[sons[x][1]];
    }
    return ;
}
inline void Clear(int x) {sons[x][0] = sons[x][1] = f[x] = sz[x] = cnt[x] = value[x] = 0;}
inline void rotate(int x) {//旋转
    int fr = f[x],g_fr = f[fr],w_son = get_which(x);
    sons[fr][w_son] = sons[x][w_son ^ 1];
    f[sons[fr][w_son]] = fr;
    sons[x][w_son ^ 1] = fr;
    f[fr] = x;
    f[x] = g_fr;
    if(g_fr) sons[g_fr][sons[g_fr][1] == fr] = x;  
    update(fr);
    update(x);
}
inline void splay(int x) {
    for(int i;i = f[x];rotate(x)) 
        if(f[i]) rotate((get_which(x) == get_which(i)) ? i : x);
    rt = x;
}
inline void insert(int x) {
    if(!rt) {
        rt = ++allsz;
        sons[allsz][0] = sons[allsz][1] = f[allsz] = 0;
        sz[allsz] = cnt[allsz]++;
        value[allsz] = x;
        return ;
    }
    int now = rt,fa = 0;
    while(1) {
        if(x == value[now]) {
            cnt[now]++;
            update(now);
            update(fa);
            splay(now);
            break;
        }
        fa = now;
        now = sons[now][value[now] < x];
        if(!now) {
            f[++allsz] = fa;
            sons[allsz][0] = sons[allsz][1] = 0;
            sz[allsz] = cnt[allsz] = 1;
            sons[fa][value[fa] < x] = allsz;
            value[allsz] = x;
            update(fa);
            splay(allsz);
            break;
        }
    }
}
inline int find_num(int x) {//查询排名为x的数
    int now = rt;
    while(1) {
        if(sons[now][0] && x <= sz[sons[now][0]]) now = sons[now][0];
        else {
            int temp = (sons[now][0] ? sz[sons[now][0]] : 0) + cnt[now];
            if(x <= temp) return value[now];
            x -= temp;
            now = sons[now][1];
        }
    }
}
inline int find_rank(int x) {//查询x的排名
    int now = rt,ans = 0;
    while(1) {
        if(x < value[now]) now = sons[now][0];
        else {
            ans += (sons[now][0] ? sz[sons[now][0]] : 0);
            if(x == value[now]) {splay(now);return ans + 1;}
            ans += cnt[now];
            now = sons[now][1];
        }
    }
}
inline int find_pre() {
    int now = sons[rt][0];
    while(sons[now][1]) now = sons[now][1];
    return now;
}
inline int find_suffix() {
    int now = sons[rt][1];
    while(sons[now][0]) now = sons[now][0];
    return now;
}
inline void Delete(int x) {
    int h = find_rank(x);
    if(cnt[rt] > 1) {cnt[rt]--;update(rt);return;}
    if(!sons[rt][0] && !sons[rt][1]) {Clear(rt);rt = 0;return;}
    if(!sons[rt][0]) {
        int old_rt = rt;
        rt = sons[rt][1];
        f[rt] = 0;
        Clear(old_rt);
        return;
    }
    else if(!sons[rt][1]) {
        int old_rt = rt;
        rt = sons[rt][0];
        f[rt] = 0;
        Clear(old_rt);
        return;
    }
    int lemx = find_pre(),old_rt = rt;
    splay(lemx);
    sons[rt][1] = sons[old_rt][1];
    f[sons[old_rt][1]] = rt;
    Clear(old_rt);
    update(rt);
}
map<int,int> mp;
void solve() {
    int n;n = read();
    LL ans = 0;
    value[0] = INF;
    for(int i = 1;i <= n;++i) {
        int x;x = read();
        insert(x);
        if(i == 1) ans += x;
        else {
            if(mp[x] != 0) continue;
            int pre = value[find_pre()];
            int nxt = value[find_suffix()];
          //  printf("pre is %d nxt is %d\n",pre,nxt);
            int ma = min(abs(x - pre),abs(x - nxt));
            ans += ma;
        }
        mp[x]++;
    }
    printf("%lld\n",ans);
}
int main() {
    solve();
    system("pause");
    return 0;
}
View Code

P3988 [SHOI2013]发牌

模拟之后可以发现,那就是它询问的点一直是询问当前序列里第pre + x小是谁。

那么就是变成了求Kth问题,splay维护一下。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
const int N = 7e5 + 5;
const int M = 2e4 + 5;
const double eps = 1e-10;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e8
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read() {
    int f = 1;int x = 0;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
inline long long ADD(long long x,long long y) {return (x + y) % Mod;}
inline long long DEC(long long x,long long y) {return (x - y + Mod) % Mod;}
inline long long MUL(long long x,long long y) {return x * y % Mod;}


int f[N],cnt[N],value[N],sons[N][2],sz[N],allsz,rt;
//allsz - 下表
inline bool get_which(int x) {return sons[f[x]][1] == x;}
inline void update(int x) {
    if(x) {
        sz[x] = cnt[x];
        if(sons[x][0]) sz[x] += sz[sons[x][0]];
        if(sons[x][1]) sz[x] += sz[sons[x][1]];
    }
    return ;
}
inline void Clear(int x) {sons[x][0] = sons[x][1] = f[x] = sz[x] = cnt[x] = value[x] = 0;}
inline void rotate(int x) {//旋转
    int fr = f[x],g_fr = f[fr],w_son = get_which(x);
    sons[fr][w_son] = sons[x][w_son ^ 1];
    f[sons[fr][w_son]] = fr;
    sons[x][w_son ^ 1] = fr;
    f[fr] = x;
    f[x] = g_fr;
    if(g_fr) sons[g_fr][sons[g_fr][1] == fr] = x;  
    update(fr);
    update(x);
}
inline void splay(int x) {
    for(int i;i = f[x];rotate(x)) 
        if(f[i]) rotate((get_which(x) == get_which(i)) ? i : x);
    rt = x;
}
inline void insert(int x) {
    if(!rt) {
        rt = ++allsz;
        sons[allsz][0] = sons[allsz][1] = f[allsz] = 0;
        sz[allsz] = cnt[allsz]++;
        value[allsz] = x;
        return ;
    }
    int now = rt,fa = 0;
    while(1) {
        if(x == value[now]) {
            cnt[now]++;
            update(now);
            update(fa);
            splay(now);
            break;
        }
        fa = now;
        now = sons[now][value[now] < x];
        if(!now) {
            f[++allsz] = fa;
            sons[allsz][0] = sons[allsz][1] = 0;
            sz[allsz] = cnt[allsz] = 1;
            sons[fa][value[fa] < x] = allsz;
            value[allsz] = x;
            update(fa);
            splay(allsz);
            break;
        }
    }
}
inline int find_num(int x) {//查询排名为x的数
    int now = rt;
    while(1) {
        if(sons[now][0] && x <= sz[sons[now][0]]) now = sons[now][0];
        else {
            int temp = (sons[now][0] ? sz[sons[now][0]] : 0) + cnt[now];
            if(x <= temp) return value[now];
            x -= temp;
            now = sons[now][1];
        }
    }
}
inline int find_rank(int x) {//查询x的排名
    int now = rt,ans = 0;
    while(1) {
        if(x < value[now]) now = sons[now][0];
        else {
            ans += (sons[now][0] ? sz[sons[now][0]] : 0);
            if(x == value[now]) {splay(now);return ans + 1;}
            ans += cnt[now];
            now = sons[now][1];
        }
    }
}
inline int find_pre() {
    int now = sons[rt][0];
    while(sons[now][1]) now = sons[now][1];
    return now;
}
inline int find_suffix() {
    int now = sons[rt][1];
    while(sons[now][0]) now = sons[now][0];
    return now;
}
inline void Delete(int x) {
    int h = find_rank(x);
    if(cnt[rt] > 1) {cnt[rt]--;update(rt);return;}
    if(!sons[rt][0] && !sons[rt][1]) {Clear(rt);rt = 0;return;}
    if(!sons[rt][0]) {
        int old_rt = rt;
        rt = sons[rt][1];
        f[rt] = 0;
        Clear(old_rt);
        return;
    }
    else if(!sons[rt][1]) {
        int old_rt = rt;
        rt = sons[rt][0];
        f[rt] = 0;
        Clear(old_rt);
        return;
    }
    int lemx = find_pre(),old_rt = rt;
    splay(lemx);
    sons[rt][1] = sons[old_rt][1];
    f[sons[old_rt][1]] = rt;
    Clear(old_rt);
    update(rt);
}
void solve() {
    int n;n = read();
    int pre = 0;
    for(int i = 1;i <= n;++i) insert(i);
    while(n--) {
        int x;x = read();
        pre += x;
        pre %= sz[rt];
        int ma = find_num(pre + 1);
        Delete(ma);
        printf("%d\n",ma);
    }
}
int main() {
    solve();
    system("pause");
    return 0;
}
View Code

SP1716 GSS3 - Can you answer these queries III

这里的核心问题就是区间最大子段和的问题。

我们进行分类讨论:分成跨越和不跨越的情况。

一开始还想得维护左右一直最大的子段的距离的,但是其实不用维护,如果跨越了那就两种:

1: 加上整段,2:加上边界开始的最大。

这里直接线段树就可以了。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
const int N = 1e5 + 5;
const int M = 2e5 + 5;
const double eps = 1e-10;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read() {
    int f = 1;int x = 0;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
inline long long ADD(long long x,long long y) {return (x + y) % Mod;}
inline long long DEC(long long x,long long y) {return (x - y + Mod) % Mod;}
inline long long MUL(long long x,long long y) {return x * y % Mod;}

int a[N];
LL mx[M << 2],le[M << 2],ri[M << 2],sum[M << 2];
struct Node{LL le,ri,sum,mx;};
void Pushup(int idx) {
    mx[idx] = max(mx[idx << 1],mx[idx << 1 | 1]);
    mx[idx] = max(mx[idx],ri[idx << 1] + le[idx << 1 | 1]);
    sum[idx] = sum[idx << 1] + sum[idx << 1 | 1];
    le[idx] = max(le[idx << 1],sum[idx << 1] + le[idx << 1 | 1]);
    ri[idx] = max(ri[idx << 1 | 1],sum[idx << 1 | 1] + ri[idx << 1]);
}
void update(int L,int r,int x,int val,int idx) {
    if(L == r) {
        mx[idx] = le[idx] = ri[idx] = sum[idx] = val;
        return ;
    }
    int mid = (L + r) >> 1;
    if(mid >= x) update(L,mid,x,val,idx << 1);
    else update(mid + 1,r,x,val,idx << 1 | 1);
    Pushup(idx);
}
Node query(int L,int r,int ll,int rr,int idx) {
    if(L >= ll && r <= rr) {
        return Node{le[idx],ri[idx],sum[idx],mx[idx]};
    }
    int mid = (L + r) >> 1;
    LL ma = -INF;
    Node ans = {ma,ma,ma,ma};
    if(mid >= ll && mid < rr) {
        Node a = query(L,mid,ll,rr,idx << 1);
        Node b = query(mid + 1,r,ll,rr,idx << 1 | 1);
        ans.mx = max(a.mx,b.mx);
        ans.mx = max(ans.mx,a.ri + b.le);
        ans.sum = a.sum + b.sum;
        ans.le = max(a.le,a.sum + b.le);
        ans.ri = max(b.ri,b.sum + a.ri);
        return ans;
    }
    else if(mid >= ll) ans = query(L,mid,ll,rr,idx << 1);
    else if(mid < rr) ans = query(mid + 1,r,ll,rr,idx << 1 | 1);
    return ans;
}
void solve() {
    int n;n = read();
    for(int i = 1;i <= n;++i) {
        a[i] = read();
        update(1,5e4,i,a[i],1);
    }
    int m;m = read();
    while(m--) {
        int id,x,y;id = read(),x = read(),y = read();
        if(id == 0) update(1,5e4,x,y,1);
        else printf("%lld\n",query(1,5e4,x,y,1).mx);
    }
}
int main() {
    solve();
    system("pause");
    return 0;
}
View Code

SP4487 GSS6 - Can you answer these queries VI

这里就在上面的题多了插入和修改。但是因为他插入后可能会改变每个位置的值,所以线段树就无法维护了。

而且线段树还多了logn的常数,甚至T了。

当我在郁闷地调试splay的时候,FHQtheap出现了。

FHQtheap:无旋theap,不像splay平衡树一样依靠旋转来维护平衡,而是通过split和merge(分裂和合并)来维护堆性质。

然后就可以做了:

注意mx[0]要赋值为无穷小因为没有节点就用0代表。

and这里其实不用卡常数,只是读入被卡了,据我观察1e5量级下scanf比read还是要快挺多的。

这里read就被卡超时了,然后scanf过了。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
const int N = 2e5 + 5;
const int M = 2e4 + 5;
const double eps = 1e-10;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read() {
    int f = 1,x = 0;char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
inline long long ADD(long long x,long long y) {return (x + y) % Mod;}
inline long long DEC(long long x,long long y) {return (x - y + Mod) % Mod;}
inline long long MUL(long long x,long long y) {return x * y % Mod;}


int val[N],sons[N][2],sz[N],pri[N],allsz = 0;
int mx[N],le[N],ri[N],sum[N];
inline void Pushup(int x) {
    sz[x] = sz[sons[x][0]] + sz[sons[x][1]] + 1;
    sum[x] = sum[sons[x][0]] + sum[sons[x][1]] + val[x];
    mx[x] = max(mx[sons[x][0]],mx[sons[x][1]]);
    mx[x] = max(mx[x],ri[sons[x][0]] + val[x] + le[sons[x][1]]);
    le[x] = max(le[sons[x][0]],sum[sons[x][0]] + val[x] + le[sons[x][1]]);
    ri[x] = max(ri[sons[x][1]],sum[sons[x][1]] + val[x] + ri[sons[x][0]]);
}
inline int new_node(int x) {
    sz[++allsz] = 1;
    val[allsz] = sum[allsz] = mx[allsz] = x;
    le[allsz] = ri[allsz] = max(x,0);
    pri[allsz] = rand();
    return allsz;
}
inline void split(int now,int k,int &x,int &y) {
    if(!now) x = y = 0;
    else {
        if(k <= sz[sons[now][0]]) y = now,split(sons[now][0],k,x,sons[now][0]);
        else x = now,split(sons[now][1],k - sz[sons[now][0]] - 1,sons[now][1],y);
        Pushup(now);
    }
}
inline int merge(int x,int y) {
    if(!x || !y) return x + y;
    if(pri[x] < pri[y]) {
        sons[x][1] = merge(sons[x][1],y);
        Pushup(x);
        return x;
    }
    else {
        sons[y][0] = merge(x,sons[y][0]);
        Pushup(y);
        return y;
    }
}
void solve() {
    int n;scanf("%d",&n);
    int rt = 0,x = 0,y = 0,z = 0;
    for(int i = 1;i <= n;++i) {
        int v;scanf("%d",&v);
        rt = merge(rt,new_node(v));
    }
    mx[0] = -1e9;
    int m;scanf("%d",&m);
    while(m--) {
        char c[2];scanf("%s",c);
        if(c[0] == 'I') {
            int L,r;scanf("%d %d",&L,&r);
            split(rt,L - 1,x,y);
            rt = merge(x,merge(new_node(r),y));
        }
        else if(c[0] == 'D') {
            int L;scanf("%d",&L);
            split(rt,L - 1,x,y);
            split(y,1,y,z);
            rt = merge(x,z);
        }
        else if(c[0] == 'R') {
            int L,r;scanf("%d %d",&L,&r);
            split(rt,L - 1,x,y);
            split(y,1,y,z);
            val[y] = r;
            Pushup(y);
            rt = merge(x,merge(y,z));
        }
        else {
            int L,r;scanf("%d %d",&L,&r);
            split(rt,r,x,y);
            split(x,L - 1,x,z);
            printf("%d\n",mx[z]);
            rt = merge(x,merge(z,y));
        }
    }
}
int main() {
    solve();
   // system("pause");
    return 0;
}
View Code

 

 https://codeforces.com/problemset/problem/600/E:

$dsu on tree维护一个val,对于最大的次数,考虑和之前做过的差不多的经典莫队来维护(也就是最大值的连续性)$

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 2e5 + 5;
const int M = 5e6 + 5;
const LL Mod = 1e9 + 7;
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

int n,c[N],Son,son[N],sz[N];
vector<int> G[N];
void dfs(int u,int fa) {
    sz[u] = 1;
    for(auto v : G[u]) {
        if(v == fa) continue;
        dfs(v,u);
        sz[u] += sz[v];
        if(sz[v] > sz[son[u]]) son[u] = v;
    }
}
int cnt[N],ct[N],mx = 0;
LL val[N],ans[N];
void modify(int u,int fa,int id) {
    if(id == 1) {
        ct[cnt[c[u]]]--;
        val[cnt[c[u]]] -= c[u];
        ct[++cnt[c[u]]]++;
        val[cnt[c[u]]] += c[u];
        mx = max(mx,cnt[c[u]]);
    }
    else {
        if(ct[cnt[c[u]]] == 1 && mx == cnt[c[u]]) mx--;
        ct[cnt[c[u]]]--;
        val[cnt[c[u]]] -= c[u];
        ct[--cnt[c[u]]]++;
        val[cnt[c[u]]] += c[u];
    }
    for(auto v : G[u]) {
        if(v == fa || v == Son) continue;
        modify(v,u,id);
    }
}
void dsu(int u,int fa,int op) {
    for(auto v : G[u]) {
        if(v == fa || v == son[u]) continue;
        dsu(v,u,0);
    }
    if(son[u]) dsu(son[u],u,1),Son = son[u];
    ct[cnt[c[u]]]--;
    val[cnt[c[u]]] -= c[u];
    ct[++cnt[c[u]]]++;
    val[cnt[c[u]]] += c[u];
    mx = max(mx,cnt[c[u]]);
    for(auto v : G[u]) {
        if(v == fa || v == son[u]) continue;
        modify(v,u,1);
    }
    ans[u] = val[mx];
    Son = 0;
    if(op == 0) modify(u,fa,-1);
 }
void solve() {
    scanf("%d",&n);
    for(int i = 1;i <= n;++i) scanf("%d",&c[i]);
    for(int i = 1;i < n;++i) {
        int x,y;scanf("%d %d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs(1,0);
    dsu(1,0,0);
    for(int i = 1;i <= n;++i) printf("%lld ",ans[i]);
}   
int main() {
    //int _;
    //for(scanf("%d",&_);_;_--) 
        solve();
    system("pause");
    return 0;
}
View Code

 

https://ac.nowcoder.com/acm/contest/4010/E:

复杂度有点难估计,一开始以为是nlognlogn。其实并不是,以为这里的set大小是在动态变化,所以复杂度应该要减少一个常数,所以能过。

维护就比较简单了,加入一个数和删去一个数的时候都维护一下贡献就行了。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 2e5 + 5;
const int M = 5e6 + 5;
const LL Mod = 1e9 + 7;
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

int n,x,sz[N],son[N],Son;
LL ans = 0,sum[N];
vector<int> G[N];
set<int> s;
void dfs(int u,int fa) {
    sz[u] = 1;
    for(auto v : G[u]) {
        dfs(v,u);
        sz[u] += sz[v];
        if(sz[son[u]] < sz[v]) son[u] = v;
    }
}
void del(LL x,LL y) {
    ans -= (y - x) * (y - x);
}
void add(LL x,LL y) {
    ans += (y - x) * (y - x);
}
void cal(int u,int id) {
    if(id == 1) {
        int L = -1,r = -1;
        auto it = s.lower_bound(u);
        if(s.size() > 0 && *(--s.end()) > u) r = *it;
        if(it != s.begin()) L = *(--it);
        if(L != -1 && r != -1) del(L,r);
        if(L != -1) add(L,u);
        if(r != -1) add(u,r);
        s.insert(u);
    }
    else {
        int L = -1,r = -1;
        auto it = s.lower_bound(u);
        if(s.size() && *(--s.end()) > u) r = *(++it),--it;
        if(it != s.begin()) L = *(--it);
        if(L != -1 && r != -1) add(L,r);
        if(L != -1) del(L,u);
        if(r != -1) del(u,r);
        s.erase(u);
    }
    for(auto v : G[u]) {
        if(v == Son) continue;
        cal(v,id);
    }
}
void dsu(int u,int op) {
    for(auto v : G[u]) {
        if(v == son[u]) continue;
        dsu(v,0);
    }
    if(son[u]) dsu(son[u],1),Son = son[u];
    int L = -1,r = -1;
    auto it = s.lower_bound(u);
    if(s.size() > 0 && *(--s.end()) > u) r = *it;
    if(it != s.begin()) L = *(--it);
    if(L != -1 && r != -1) del(L,r);
    if(L != -1) add(L,u);
    if(r != -1) add(u,r);
    s.insert(u);
    for(auto v : G[u]) {
        if(v == son[u]) continue;
        cal(v,1);
    }
    Son = 0;
    sum[u] = ans;
    if(op == 0) cal(u,-1);
}
void solve() {
    scanf("%d",&n);
    for(int i = 2;i <= n;++i) scanf("%d",&x),G[x].push_back(i);
    dfs(1,0);
    dsu(1,0);
    for(int i = 1;i <= n;++i) printf("%lld\n",sum[i]);
}   
int main() {
    //int _;
    //for(scanf("%d",&_);_;_--) 
        solve();
    system("pause");
    return 0;
}
/*
10
1
1
2
2
3
3
4
4
5

*/
View Code

 

posted @ 2021-09-26 13:50  levill  阅读(40)  评论(0)    收藏  举报