专项测试(数据结构2)

专项测试(数据结构2)

不不不不不是数据结构,是煞笔题,是垃圾题

是给码不给题解的题

是摇摆兵不会的题

\(pyt\)爆切\(T2\)的题

是我改不完的题

T1 学军题

不会

T2 CF571D

这个做法非常多,我是启发式合并+主席树

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const int N=1e5+5;
int n,m,a[N];
vector<int> s[N],t[N];
struct node{int id,p;};
vector<node> bs[N],bt[N];
vector<int> sim[N];
int ssz[N],tsz[N];
int is[N],it[N];
struct Q{int tp,x,y;}q[N*5];
int srt[N],trt[N];
struct sZXS{
    struct POT{
        int ls,rs;ll sum;
    }tr[N*4*18];
    int seg;
    int newpot(int x){
        ++seg;tr[seg]=tr[x];
        return seg;
    }
    void ins(int &x,int l,int r,int ql,int qr,int v){
        x=newpot(x);
        if(ql<=l&&r<=qr)return tr[x].sum+=v,void();
        int mid=l+r>>1;
        if(ql<=mid)ins(tr[x].ls,l,mid,ql,qr,v);
        if(qr>mid)ins(tr[x].rs,mid+1,r,ql,qr,v);
    }
    ll query(int pr,int x,int l,int r,int pos){
        if(l==r)return tr[x].sum-tr[pr].sum;
        int mid=l+r>>1;
        if(pos<=mid)return query(tr[pr].ls,tr[x].ls,l,mid,pos)+tr[x].sum-tr[pr].sum;
        else return query(tr[pr].rs,tr[x].rs,mid+1,r,pos)+tr[x].sum-tr[pr].sum;
    }
}sz;
struct tZXS{
    struct POT{
        int mx,ls,rs;
    }tr[N*4*18];
    int seg;
    int newpot(int x){
        ++seg;tr[seg]=tr[x];
        return seg;
    }
    void ins(int &x,int l,int r,int ql,int qr,int v){
        if(!x)x=newpot(x);
        if(ql<=l&&r<=qr)return tr[x].mx=v,void();
        int mid=l+r>>1;
        if(ql<=mid)ins(tr[x].ls,l,mid,ql,qr,v);
        if(qr>mid)ins(tr[x].rs,mid+1,r,ql,qr,v);
    }
    int query(int x,int l,int r,int pos){
        if(!x)return 0;
        if(l==r)return tr[x].mx;
        int mid=l+r>>1;
        if(pos<=mid)return max(query(tr[x].ls,l,mid,pos),tr[x].mx);
        else return max(query(tr[x].rs,mid+1,r,pos),tr[x].mx);
    }
}tz;
signed main(){
    n=read();m=read();
    fo(i,1,n){
        s[i].push_back(i);bs[i].push_back(node{i,0});
        t[i].push_back(i);bt[i].push_back(node{i,0});
        ssz[i]=1;tsz[i]=1;
    }
    fo(i,1,m){
        char tp[5];scanf("%s",tp+1);
        int x=read(),y;
        if(tp[1]=='U'){
            q[i].tp=1;q[i].x=x;q[i].y=y=read();
            int nx=bs[x].rbegin()->id,ny=bs[y].rbegin()->id;
            if(nx==ny)continue;
            if(ssz[nx]>=ssz[ny]){
                for(int i:s[ny]){
                    s[nx].push_back(i);
                    bs[i].push_back(node{nx,ssz[nx]});
                    ssz[nx]++;
                }
            }
            else {
                for(int i:s[nx]){
                    s[ny].push_back(i);
                    bs[i].push_back(node{ny,ssz[ny]});
                    ssz[ny]++;
                }
            }
        }
        if(tp[1]=='M'){
            q[i].tp=2;q[i].x=x;q[i].y=y=read();
            int nx=bt[x].rbegin()->id,ny=bt[y].rbegin()->id;
            if(nx==ny)continue;
            if(tsz[nx]>=tsz[ny]){
                for(int i:t[ny]){
                    t[nx].push_back(i);
                    bt[i].push_back(node{nx,tsz[nx]});
                    tsz[nx]++;
                }
            }
            else {
                for(int i:t[nx]){
                    t[ny].push_back(i);
                    bt[i].push_back(node{ny,tsz[ny]});
                    tsz[ny]++;
                }
            }
        }
        if(tp[1]=='A'){
            q[i].tp=3;q[i].x=x;
        }
        if(tp[1]=='Z'){
            q[i].tp=4;q[i].x=x;
        }
        if(tp[1]=='Q'){
            q[i].tp=5;q[i].x=x;
        }
    }
    fo(i,1,n){
        ssz[i]=tsz[i]=1;
        is[i]=it[i]=0;
        sim[i].push_back(0);
    }
    fo(mm,1,m){
        int tp=q[mm].tp,x=q[mm].x,y=q[mm].y;
        if(tp==1){
            int nx=bs[x][is[x]].id,ny=bs[y][is[y]].id;
            if(nx==ny)continue;
            if(ssz[nx]>=ssz[ny]){
                for(int i:s[ny])is[i]++;
                ssz[nx]+=ssz[ny];
            }
            else {
                for(int i:s[nx])is[i]++;
                ssz[ny]+=ssz[nx];
            }
        }
        if(tp==2){
            int nx=bt[x][it[x]].id,ny=bt[y][it[y]].id;
            if(nx==ny)continue;
            if(tsz[nx]>=tsz[ny]){
                for(int i:t[ny])it[i]++;
                tsz[nx]+=tsz[ny];
            }
            else {
                for(int i:t[nx])it[i]++;
                tsz[ny]+=tsz[nx];
            }
        }
        if(tp==3){
            int nx=bs[x][is[x]].id;
            int lst=*sim[nx].rbegin();
            sim[nx].push_back(mm);srt[mm]=srt[lst];
            int R=s[nx].size()-1;
            sz.ins(srt[mm],0,R,0,ssz[nx]-1,ssz[nx]);
        }
        if(tp==4){
            int nx=bt[x][it[x]].id;
            int R=t[nx].size()-1;
            tz.ins(trt[nx],0,R,0,tsz[nx]-1,mm);
        }
        if(tp==5){
            int lim=0;ll ans=0;
            for(node i:bt[x]){
                int nx=i.id;
                int R=t[nx].size()-1;
                lim=max(lim,tz.query(trt[nx],0,R,i.p));
                if(i.id==bt[x][it[x]].id)break;
            }
            for(node i:bs[x]){
                int nx=i.id;
                int R=s[nx].size()-1;
                vector<int>::iterator pos=upper_bound(sim[nx].begin(),sim[nx].end(),lim);
                if(pos!=sim[nx].end()){
                    ans+=sz.query(srt[*prev(pos)],srt[*sim[nx].rbegin()],0,R,i.p);
                }
                if(i.id==bs[x][is[x]].id)break;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

T3 counting on tree

这个直接斜率优化,用\(set\)维护凸包,因为横坐标无序

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=1e6+5;
int n,a[N],ans;
int fa[N],sum[N],son[N];
int to[N],nxt[N],head[N],rp;
void add_edg(int x,int y){
    to[++rp]=y;
    nxt[rp]=head[x];
    head[x]=rp;
}
int dp[N],tg[N];
struct node{
    int x,y;
    bool operator < (node a)const{return x<a.x;}
};
double k(node a,node b){return 1.0*(a.y-b.y)/(a.x-b.x);}
bool comp(node a,node b,node c){return k(a,b)<k(b,c);}
int pw(int x){return x*x;}
set<node> s[N];
void ins(int x,node v){
    v.y-=tg[x];
    set<node>::iterator it=s[x].lower_bound(v);
    if(it!=s[x].end()&&it->x==v.x){
        if(it->y<=v.y)return ;
        else s[x].erase(it);
    }
    while(!s[x].empty()){
        set<node>::iterator i=s[x].lower_bound(v);
        if(i==s[x].begin())break;
        i--;if(i==s[x].begin())break;
        set<node>::iterator j=prev(i);
        if(!comp(*j,*i,v))s[x].erase(i);
        else break;
    }
    while(!s[x].empty()){
        set<node>::iterator i=s[x].lower_bound(v);
        if(i==s[x].end())break;
        set<node>::iterator j=next(i);
        if(j==s[x].end())break;
        if(!comp(v,*i,*j))s[x].erase(i);
        else break;
    }
    set<node>::iterator i=s[x].lower_bound(v);
    if(i==s[x].begin()||i==s[x].end())return s[x].insert(v),void();
    set<node>::iterator j=prev(i);
    if(comp(*j,v,*i))s[x].insert(v);
}
int get(int x){
    if(s[x].empty())return inf;
    node ret;
    if(s[x].size()==1)ret=*s[x].begin();
    else {
        int l=s[x].begin()->x,r=s[x].rbegin()->x,mid;
        while(l<r){
            mid=l+r+1>>1;
            set<node>::iterator it=s[x].lower_bound(node{mid,-inf});
            if(it==s[x].begin()){l=mid;continue;}
            node i=*prev(it),j=*it;
            i.y+=tg[x];j.y+=tg[x];
            if(k(i,j)>=2*sum[fa[x]])r=mid-1;
            else l=mid;
        }
        ret=*s[x].lower_bound(node{l,-inf});
    }
    ret.y+=tg[x];
    return pw(sum[fa[x]])-2*sum[fa[x]]*ret.x+ret.y;
}
void dfs(int x){
    sum[x]=sum[fa[x]]+a[x];int mx=0;
    for(int i=head[x];i;i=nxt[i]){
        dfs(to[i]);son[x]+=dp[to[i]];
        if(s[to[i]].size()>s[mx].size())mx=to[i];
    }
    swap(s[x],s[mx]);tg[x]=tg[mx]+son[x]-dp[mx];
    for(int i=head[x];i;i=nxt[i]){
        if(to[i]==mx)continue;
        tg[to[i]]+=son[x]-dp[to[i]];
        for(node j:s[to[i]])j.y+=tg[to[i]],ins(x,j);
    }
    dp[x]=min(get(x),son[x]+pw(a[x]));
    ins(x,node{sum[x],son[x]+pw(sum[x])});
}
signed main(){
    n=read();
    fo(i,1,n)a[i]=read();
    fo(i,2,n)fa[i]=read(),add_edg(fa[i],i);
    dfs(1);printf("%lld",dp[1]);
    return 0;
}
posted @ 2021-12-19 19:23  fengwu2005  阅读(31)  评论(0编辑  收藏  举报