模拟测试10 T2:模板
大方面:
启发式合并。
轻的合并到重的里。
处理轻儿子,清空。继承重儿子。
基于时间线段树:信息处理。
信息存储:开数组。:vector.
开数组而不必线段树合并:线段树合并无法处理种类计数,重复。因此不能合并。因此不必每个点开线段树。
如果要合并是为了继承之前的信息。但无法直接继承。而且打标记能够O(1)清空。所以不必浪费空间。
为处理要处理的信息要把决策点一个一个放到线段树里处理。因此要存储。用数组,vector。
线段树清空:打标记。标记的使用。
处理重复的信息不好直接在线段树内部操作:考虑两个方向:1、打标记 。但几乎没有标记能解决。
2、辅助数组直接记出现的最早的时间。一个个向里放。
如何想到一个个向里放:启发式合并就是继承重的,轻的一个个向里放。
Ps:昨天没理解请启发式合并。但lnc告诉他后明白了。应该去问他问明白启发式合并的流程。
启发式合并一个个统计(向里放)是nlog的。
我的帅比代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 */
我们的红太阳,日本搭次客的秋田犬,exface脸的lowbi指针打法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
Informatik verbindet dich und mich.
信息将你我连结。