hdu4358 線段樹之離線累加處理
阿新 • • 發佈:2019-02-06
思路:
1.用前向星建圖,然後先把樹處理成區間;
2.對詢問按右邊界排序,將權重離散化;
3.離線處理,sum[k]記錄k~i之間的k次權值數;
4.每次將k次的段+1,k+1次的段-1.
ACcode:
#include<cstdio> #include<vector> #include<iostream> #include<algorithm> using std::vector; using std::sort; const int nsize=111111; int n,q,pos; int *p[nsize]; int a[nsize],num[nsize]; int sum[nsize<<2],cov[nsize<<2]; int e[nsize<<1],next[nsize<<1],head[nsize]; vector<int> lst[nsize]; struct Line { int l,r; } line[nsize]; struct qry { int id,l,r; bool operator <(const qry &cmp) const{ return r<cmp.r; } } qry[nsize]; void dfs(int rt) { num[rt]=1; line[rt].l=pos; for (int i=head[rt]; i>0; i=next[i]) if (!num[e[i]]) pos++,dfs(e[i]); line[rt].r=pos; } void build(int rt,int l,int r) { sum[rt]=cov[rt]=0; if (l==r) return ; int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r); } bool cmp(int *a1,int *a2) { return *a1<*a2; } void PushDown(int rt) { sum[rt<<1]+=cov[rt]; cov[rt<<1]+=cov[rt]; sum[rt<<1|1]+=cov[rt]; cov[rt<<1|1]+=cov[rt]; cov[rt]=0; } void update(int rt,int l,int r,int L,int R,int v) { if (L<=l&&r<=R) { sum[rt]+=v; cov[rt]+=v; return ; } if (cov[rt]) PushDown(rt); int m=(l+r)>>1; if (L<=m) update(rt<<1,l,m,L,R,v); if (R>m) update(rt<<1|1,m+1,r,L,R,v); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } int query(int rt,int l,int r,int ps) { if (l==r) return sum[rt]; if (cov[rt]) PushDown(rt); int m=(l+r)>>1; if (ps<=m) return query(rt<<1,l,m,ps); else return query(rt<<1|1,m+1,r,ps); } void add(int u,int v,int i) { e[i]=v; next[i]=head[u]; head[u]=i; } int main() { int T,cas=0; int k,i,j,u,v,rt,top; scanf("%d",&T); while (T--) { scanf("%d %d",&n,&k); for (top=i=1; i<=n; i++) { scanf("%d",&a[i]); p[i]=&a[i]; lst[i].clear(); head[i]=num[i]=0; } for (i=1; i<n; i++) { scanf("%d %d",&u,&v); add(u,v,i+i-1); add(v,u,i+i); } pos=1,dfs(1); scanf("%d",&q); for (i=1; i<=q; i++) { qry[i].id=i; scanf("%d",&u); qry[i].l=line[u].l; qry[i].r=line[u].r; } sort(p+1,p+n+1,cmp); sort(qry+1,qry+q+1); v=*p[1],*p[1]=1,u=1; for (i=2; i<=n; i++) { if (*p[i]!=v) v=*p[i],u++; *p[i]=u; } build(1,1,n); for (j=i=1; i<=q; i++) { while (j<=qry[i].r&&j<=n) { v=a[j]; lst[v].push_back(j); u=lst[v].size(); if (u==k) update(1,1,n,1,lst[v][u-k],1); else if (u>k) { update(1,1,n,lst[v][u-k-1]+1,lst[v][u-k],1); update(1,1,n,(u>k+1?lst[v][u-k-2]:0)+1,lst[v][u-k-1],-1); } j++; } num[qry[i].id]=query(1,1,n,qry[i].l); } if (cas) printf("\n"); printf("Case #%d:\n",++cas); for (i=1; i<=q; i++) printf("%d\n",num[i]); } return 0; }