首页 > 技术文章 > 模拟测试10 T2:模板

seamtn 2019-07-30 15:43 原文

大方面:

启发式合并。

轻的合并到重的里。

处理轻儿子,清空。继承重儿子。

基于时间线段树:信息处理。

信息存储:开数组。:vector.

开数组而不必线段树合并:线段树合并无法处理种类计数,重复。因此不能合并。因此不必每个点开线段树。

如果要合并是为了继承之前的信息。但无法直接继承。而且打标记能够O(1)清空。所以不必浪费空间。

为处理要处理的信息要把决策点一个一个放到线段树里处理。因此要存储。用数组,vector。

线段树清空:打标记。标记的使用。

处理重复的信息不好直接在线段树内部操作:考虑两个方向:1、打标记 。但几乎没有标记能解决。

2、辅助数组直接记出现的最早的时间。一个个向里放。

如何想到一个个向里放:启发式合并就是继承重的,轻的一个个向里放。

 

Ps:昨天没理解请启发式合并。但lnc告诉他后明白了。应该去问他问明白启发式合并的流程。

  启发式合并一个个统计(向里放)是nlog的。

我的帅比代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define F(i,a,b) for(rg int i=a;i<=b;++i)
#define il inline 
#define LL long long
#define phn printf("\n")
#define pf(a) printf("%d ",a)
#define rg register
#define cri const register int
using namespace std;
int read();
#define NX 100010
int n,m,Q,ban[NX];
int to[NX<<1],fir[NX<<1],head[NX],cnt;
il void add(const int x,const int y){
    to[++cnt]=y;fir[cnt]=head[x];head[x]=cnt;
}
int adx[NX],b[NX],c[NX],id[NX];
vector<pair<int,int> >q[NX];
#define mp(a,b) make_pair(a,b)
int son[NX],sz[NX];
#define qxs(i,x) for(int i=head[x];i;i=fir[i])
#define V to[i]
void sear(int x,int fa){
    sz[x]=q[x].size();
    qxs(i,x){
        if(V!=fa){
            sear(V,x);
            sz[x]+=sz[V];
            if(!son[x]||sz[V]>sz[son[x]])son[x]=V;
        }
    }
}    
int tong[NX],ans[NX];
struct node{
    int sum,w,cl,l,r;
}s[NX<<2];
#define lc s[x<<1]
#define rc s[x<<1|1]
#define sx s[x]
#define MIT int z=(s[x].l+s[x].r)>>1
void biuld(int x,int l,int r){
    s[x].l=l;s[x].r=r;sx.w=sx.sum=sx.cl=0;
    if(l==r)return ;
    MIT;biuld(x<<1,l,z);biuld(x<<1|1,z+1,r);
}
il void down(int x){
    lc.sum=lc.w=rc.sum=rc.w=0;
    lc.cl=rc.cl=1;
    sx.cl=0;
}
void chg(int x,int k,int d){
    if(sx.l==sx.r){
        sx.w=d;sx.sum=1;return ;
    }
    if(sx.cl)down(x);MIT;
    if(k<=z)chg(x<<1,k,d);
    else chg(x<<1|1,k,d);
    sx.w=lc.w+rc.w;
    sx.sum=lc.sum+rc.sum;
}
int ask(int x,int k){
    if(sx.sum<=k){//<=???
        return sx.w;
    }
    if(sx.cl)down(x);
    if(lc.sum>=k)return ask(x<<1,k);
    else {
        return ask(x<<1,lc.sum)+ask(x<<1|1,k-lc.sum);
    }
}
void dfs(int x,int fa){
    qxs(i,x){
        if(V!=fa&&V!=son[x]){
            dfs(V,x);
            int end=q[id[V]].size()-1;
            F(j,0,end){
                tong[q[id[V]][j].first]=0;
            //    q[x].push_back(q[V][j]);
            }
            s[1].cl=1;s[1].sum=s[1].w=0;
            //q[V].clear();
        }
    }
    if(son[x])dfs(son[x],x);
    int end=q[id[x]].size()-1;
    F(i,0,end){
        cri col=q[id[x]][i].first,t=q[id[x]][i].second;
        if(son[x])q[id[son[x]]].push_back(q[id[x]][i]);
        if(!tong[col]){
            tong[col]=t;
            chg(1,t,1);
        }
        else{
            if(tong[col]>t){
                chg(1,tong[col],0);
                tong[col]=t;
                chg(1,t,1);
            }
            else {
                chg(1,t,0);
            }
        }
    }
    if(son[x])swap(id[x],id[son[x]]);
    qxs(i,x){
        if(V!=fa&&V!=son[x]){
            end=q[id[V]].size()-1;
            F(j,0,end){
                int col=q[id[V]][j].first,t=q[id[V]][j].second;
                q[id[x]].push_back(q[id[V]][j]);
                if(!tong[col]){
                    tong[col]=t;
                    chg(1,t,1);
                }
                else{
                    if(tong[col]>t){
                        chg(1,tong[col],0);
                        tong[col]=t;
                        chg(1,t,1);
                    }
                    else {
                        chg(1,t,0);
                    }
                }
            }
        }
    }
    ans[x]=ask(1,ban[x]);//pf(end);phn;
}
int main(){
    n=read();rg int x,y;
    F(i,2,n){
        x=read();y=read();add(x,y);add(y,x);
    }
    F(i,1,n)ban[i]=read();
    m=read();
    F(i,1,m){
        adx[i]=read();b[i]=c[i]=read();
    }
    sort(c+1,c+m+1);
    int g=unique(c+1,c+m+1)-c-1;
    F(i,1,m)b[i]=lower_bound(c+1,c+g+1,b[i])-c;
    F(i,1,m){
        q[adx[i]].push_back(mp(b[i],i));
    }
    F(i,1,n)id[i]=i;
    sear(1,0);
    biuld(1,1,NX);
    dfs(1,0);
    Q=read();
    F(i,1,Q){
        x=read();
        printf("%d\n",ans[x]);
    }
}
il int read(){
    int s=0,f=0;char ch;
    while(ch=getchar(),ch=='-'?f=1:0,ch<'0'||ch>'9');
    while(ch>='0'&&ch<='9'){
        s=s*10+(ch^48);ch=getchar();
    }
    return f?-s:s;
}
/*
g++ 1.cpp -g
./a.out
10
3 10
2 5
3 2
2 6
1 9
8 7
7 4
3 8
3 1
15 47 23 22 9 16 45 39 21 13
10
10 7
9 3
5 1
5 2
9 4
10 9
2 4
10 1
2 6
7 9
3
1
2
3


*/
View Code

我们的红太阳,日本搭次客的秋田犬,exface脸的lowbi指针打法:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<map>
using namespace std;
const int N=100010;
map<int,int> mp;
vector<pair<int,int> > ve[N];//time color
int n,m,q,ct;
int tot,head[N],nxt[N*2],to[N*2];
int k[N],ans[N],size[N],son[N],fir[N];
struct segtree{
    struct node{
        node *lch,*rch;
        int sum,cnt;
        void update(){
            sum=(lch?lch->sum:0)+(rch?rch->sum:0);
            cnt=(lch?lch->cnt:0)+(rch?rch->cnt:0);
        }
    }pool[N*100],*root;
    int cnt;
    node *New(){
        pool[++cnt].lch=pool[cnt].rch=0;
        pool[cnt].cnt=pool[cnt].sum=0;
        return &pool[cnt];
    }
    void valadd(node *&p,int l,int r,int pos,int add)
    {
        if(!p) p=New();
        if(l==r) return (void)(p->sum+=add);
        int mid=l+r>>1;
        if(pos<=mid) valadd(p->lch,l,mid,pos,add);
        else valadd(p->rch,mid+1,r,pos,add);
        p->update();
    }
    void cntadd(node *&p,int l,int r,int pos)
    {
        if(!p) p=New();
        if(l==r) return (void)(++p->cnt);
        int mid=l+r>>1;
        if(pos<=mid) cntadd(p->lch,l,mid,pos);
        else cntadd(p->rch,mid+1,r,pos);
        p->update();
    }
    int query(node *p,int k,int l,int r){
        if(!p) return 0;
        if(k>=p->cnt) return p->sum;
        int mid=l+r>>1;
        if((p->lch?p->lch->cnt:0)>=k) return query(p->lch,k,l,mid);
        return query(p->rch,k-(p->lch?p->lch->cnt:0),mid+1,r)+(p->lch?p->lch->sum:0);
    }
    void clear(){
        cnt=0; root=0;
    }
}st;
inline void add(int a,int b){
    to[++tot]=b;
    nxt[tot]=head[a];
    head[a]=tot;
}
inline int read(){
    int x; scanf("%d",&x);
    return x;
}
void pre(int x,int fa){
    for(int i=head[x];i;i=nxt[i]){
        if(to[i]==fa) continue;
        pre(to[i],x);
        size[x]+=size[to[i]];
        if(size[to[i]]>=size[son[x]]) son[x]=to[i];
    }
    size[x]+=ve[x].size()+1;
}
void dfsupdate(int x,int fa){
    for(int i=head[x];i;i=nxt[i])
        if(to[i]!=fa) dfsupdate(to[i],x);
    for(int i=0;i<ve[x].size();++i){
        st.cntadd(st.root,1,m,ve[x][i].first);
        if(!fir[ve[x][i].second]){
            st.valadd(st.root,1,m,ve[x][i].first,1);
            fir[ve[x][i].second]=ve[x][i].first;
        }
        else if(ve[x][i].first < fir[ve[x][i].second]){
            st.valadd(st.root,1,m,ve[x][i].first,1);
            st.valadd(st.root,1,m,fir[ve[x][i].second],-1);
            fir[ve[x][i].second]=ve[x][i].first;
        }
    }
}
void dfsremove(int x,int fa){
    for(int i=head[x];i;i=nxt[i])
        if(to[i]!=fa) dfsremove(to[i],x);
    for(int j=0;j<ve[x].size();++j) fir[ve[x][j].second]=0;
}
void dfs(int x,int fa){
    for(int i=head[x];i;i=nxt[i])
        if(to[i]!=fa&&to[i]!=son[x])
        {
            dfs(to[i],x);
            st.clear(); dfsremove(to[i],x);
        }
    if(son[x]) dfs(son[x],x);
    for(int i=0;i<ve[x].size();++i)
    {
        st.cntadd(st.root,1,m,ve[x][i].first);
        if(!fir[ve[x][i].second]){
            st.valadd(st.root,1,m,ve[x][i].first,1);
            fir[ve[x][i].second]=ve[x][i].first;
        }
        else if(ve[x][i].first < fir[ve[x][i].second]){
            st.valadd(st.root,1,m,ve[x][i].first,1);
            st.valadd(st.root,1,m,fir[ve[x][i].second],-1);
            fir[ve[x][i].second]=ve[x][i].first;
        }
    }
    for(int i=head[x];i;i=nxt[i])
        if(to[i]!=fa&&to[i]!=son[x]) dfsupdate(to[i],x);
    ans[x]=st.query(st.root,k[x],1,m);
}
int main(){
    //freopen("x.in","r",stdin);
    //freopen("me.out","w",stdout);
    scanf("%d",&n);
    for(int i=1,a,b;i<n;++i){
        scanf("%d%d",&a,&b);
        add(a,b); add(b,a);
    }
    for(int i=1;i<=n;++i) scanf("%d",&k[i]);
    scanf("%d",&m);
    for(int i=1,a,b;i<=m;++i){
        scanf("%d%d",&a,&b);
        if(!mp[b]) mp[b]=++ct;
        ve[a].push_back(make_pair(i,mp[b]));
    }
    pre(1,0);
    dfs(1,0);
    scanf("%d",&q);
    while(q--) printf("%d\n",ans[read()]);
    return 0;
}
View Code

 

推荐阅读