做题记录:P2146 [NOI2015] 软件包管理器

树剖模板题,要求的操作时候区间平推,区间和查询。

这还不简单?我会珂朵莉树!

然而我打了珂线段树:

直接一发A掉。

#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 1919810
#define lc p<<1
#define rc p<<1|1 
using namespace std;
int n,m,rt=1919000;
int head[N],to[N],nxt[N],tot,id[N],son[N],f[N],idx,siz[N],dep[N],top[N];
void add(int u,int v){
    to[++tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}
struct Segement_tree{
    int l,r,val,tag;
}s[8*N];
void build(int p,int l,int r){
    s[p].l=l,s[p].r=r;s[p].tag=-1;
    if(l==r)return;
    build(lc,l,(l+r)/2);
    build(rc,(l+r)/2+1,r);
}
void pushup(int p){s[p].val=s[lc].val+s[rc].val;}
void pushdown(int p){
    if(s[p].tag==-1)return;
    s[lc].tag=s[p].tag;s[rc].tag=s[p].tag;
    s[lc].val=s[p].tag*(s[lc].r-s[lc].l+1);
    s[rc].val=s[p].tag*(s[rc].r-s[rc].l+1);
    s[p].tag=-1; 
} 
void assign(int p,int l,int r,int v){
    if(s[p].l>r||s[p].r<l)return;
    if(s[p].l>=l&&s[p].r<=r){
        s[p].val=v*(s[p].r-s[p].l+1);
        s[p].tag=v;
        return;
    }
    pushdown(p);
    assign(lc,l,r,v);assign(rc,l,r,v);
    pushup(p);
}
int query(int p,int l,int r){
    if(s[p].l>r||s[p].r<l)return 0;
    if(s[p].l>=l&&s[p].r<=r)return s[p].val;
    pushdown(p);
    return query(lc,l,r)+query(rc,l,r);
}
void dfs1(int x,int fa){
    dep[x]=dep[fa]+1;siz[x]=1;f[x]=fa;
    int maxn=-1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa)continue;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>maxn)maxn=siz[y],son[x]=y;
    }
}
void dfs2(int x,int topx){
    id[x]=++idx,top[x]=topx;
    if(!son[x])return;
    dfs2(son[x],topx);
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==f[x]||y==son[x])continue;
        dfs2(y,y);
    }
}
void change(int x,int y,int v){
    while(top[x]!=top[y]){
        //printf("%d\n",x);
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        assign(1,id[top[x]],id[x],v);x=f[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    assign(1,id[x],id[y],v);
}
void assub(int x,int v){assign(1,id[x],id[x]+siz[x]-1,v);}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int a;
        scanf("%d",&a);
        if(a==0)a=rt;
        add(i,a);add(a,i);
    }dfs1(rt,rt);dfs2(rt,rt);
    build(1,1,idx);
    scanf("%d",&m);
    while(m--){
        char s[26];
        int a;
        scanf("%s%d",s,&a);
        if(a==0)a=rt;
        if(s[0]=='i'){
            int yl=query(1,id[rt],id[rt]+siz[rt]-1);
            change(rt,a,1);
            printf("%d\n",abs(query(1,id[rt],id[rt]+siz[rt]-1)-yl));
        }else{
            int yl=query(1,id[rt],id[rt]+siz[rt]-1);
            assub(a,0);
            printf("%d\n",abs(query(1,id[rt],id[rt]+siz[rt]-1)-yl));
        }
    }
    return 0;
}

打完之后我心血来潮想试试珂朵莉树珂不珂以过:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#define N 1919810
#define ct Chtholly_tree
#define Chtholly set<ct>::iterator
using namespace std;
int n,m,rt=1919000;
int head[N],to[N],nxt[N],tot,id[N],son[N],f[N],idx,siz[N],dep[N],top[N];
void add(int u,int v){
    to[++tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}
struct Chtholly_tree{
    int l,r;
    mutable int val;
    ct(int a=0,int b=0,int c=0){l=a,r=b,val=c;}
    bool operator <(const ct &c)const{return l<c.l;}
};
set<ct>st;
Chtholly split(int p){
    Chtholly it=st.lower_bound(ct(p,0,0));
    if(it!=st.end()&&it->l==p)return it;
    it--;ct tmp=*it;st.erase(it);
    st.insert(ct(tmp.l,p-1,tmp.val));
    return st.insert(ct(p,tmp.r,tmp.val)).first;
}
void assign(int l,int r,int v){
    Chtholly right=split(r+1),left=split(l);
    st.erase(left,right);
    st.insert(ct(l,r,v));
}
int query(int l,int r){
    Chtholly right=split(r+1),left=split(l);
    int ans=0;
    for(;left!=right;left++)ans+=left->val*(left->r-left->l+1);
    return ans;
}
void dfs1(int x,int fa){
    dep[x]=dep[fa]+1;siz[x]=1;f[x]=fa;
    int maxn=-1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa)continue;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>maxn)maxn=siz[y],son[x]=y;
    }
}
void dfs2(int x,int topx){
    id[x]=++idx,top[x]=topx;
    if(!son[x])return;
    dfs2(son[x],topx);
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==f[x]||y==son[x])continue;
        dfs2(y,y);
    }
}
void change(int x,int y,int v){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        assign(id[top[x]],id[x],v);x=f[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    assign(id[x],id[y],v);
}
void assub(int x,int v){assign(id[x],id[x]+siz[x]-1,v);}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int a;
        scanf("%d",&a);
        if(a==0)a=rt;
        add(i,a);add(a,i);
    }dfs1(rt,rt);dfs2(rt,rt);
    st.insert(ct(0,2147483647,0));
    scanf("%d",&m);
    while(m--){
        char s[26];
        int a;
        scanf("%s%d",s,&a);
        if(a==0)a=rt;
        if(s[0]=='i'){
            int yl=query(id[rt],id[rt]+siz[rt]-1);
            change(rt,a,1);
            printf("%d\n",abs(query(id[rt],id[rt]+siz[rt]-1)-yl));
        }else{
            int yl=query(id[rt],id[rt]+siz[rt]-1);
            assub(a,0);
            printf("%d\n",abs(query(id[rt],id[rt]+siz[rt]-1)-yl));
        }
    }
    return 0;
}

冰冷的事实告诉我,这道题珂朵莉树只能得70分(TAT)。

在我巨大的提交次数上白白增加了2(

完结撒花(

posted @ 2022-08-25 11:48  灵长同志  阅读(14)  评论(0)    收藏  举报