//hdu 2665 这里就做为划分树模板了;
#include<stdio.h> #include<algorithm> using namespace std; #define N 100100 int data[N]; struct node { int v[N]; int num[N]; }td[31]; void build(int l,int r,int dep) { if(l>=r)return; int i,mid=(l+r)>>1,midd=data[mid],ant=mid-l+1; int ln=l-1,rn=mid; for(i=l;i<=r;i++) if(td[dep].v[i]<midd) ant--; for(i=l;i<=r;i++) { if(i==l) td[dep].num[i]=0; else td[dep].num[i]=td[dep].num[i-1]; if(td[dep].v[i]<midd||(td[dep].v[i]==midd&&ant)) { if(td[dep].v[i]==midd)--ant; td[dep+1].v[++ln]=td[dep].v[i]; ++td[dep].num[i]; } else td[dep+1].v[++rn]=td[dep].v[i]; } build(l,mid,dep+1); build(mid+1,r,dep+1); } int query(int a,int b,int k,int l,int r,int dep) { int mid=(l+r)>>1; if(a==b)return td[dep].v[a]; int lx,rx=td[dep].num[b],sub,sl,sr; lx=(a<=l)?0:td[dep].num[a-1]; sub=rx-lx; if(sub>=k) return query(l+lx,l+rx-1,k,l,mid,dep+1); else { sl=a-l-lx; sr=b-l-rx; return query(mid+1+sl,mid+1+sr,k-sub,mid+1,r,dep+1); } } int main() { int i,cas,n,m,l,r,k; scanf("%d",&cas); while(cas--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&td[1].v[i]); data[i]=td[1].v[i]; } sort(data+1,data+n+1); build(1,n,1); while(m--) { scanf("%d%d%d",&l,&r,&k); printf("%d\n",query(l,r,k,1,n,1)); } } return 0; }
/*
//
csu 上的一道划分树求前k大的和的题;
划分树的关键在于的它的划分,以及它的那个记录当前点前面有多少被划分到左子树的辅助数组,真的很巧妙;
这道题还需要一个sum数组来辅助计算;
*/
#include<stdio.h> #include<algorithm> using namespace std; #define N 10100 struct nd { int dul; int v; }data[N]; struct node { nd v[N]; int num[N]; int sum[N]; }td[31]; int pre[N]; bool cmp(nd a,nd b){return a.dul<b.dul;} bool cmp_(nd a,nd b){return a.v>b.v;} void build(int l,int r,int dep) { if(l>=r)return; int i,mid=(l+r)>>1,midd=data[mid].v,ant=mid-l+1; int ln=l-1,rn=mid; for(i=l;i<=r;i++) if(td[dep].v[i].v>midd) ant--; for(i=l;i<=r;i++) { if(i==l) td[dep].num[i]=td[dep+1].sum[ln+1]=td[dep+1].sum[rn+1]=0; else td[dep].num[i]=td[dep].num[i-1]; if(td[dep].v[i].v>midd||(td[dep].v[i].v==midd&&ant)) { if(td[dep].v[i].v==midd)--ant; td[dep+1].v[++ln].v=td[dep].v[i].v; if(ln!=l) td[dep+1].sum[ln]=td[dep+1].sum[ln-1]; td[dep+1].sum[ln]+=td[dep].v[i].v; ++td[dep].num[i]; } else{ td[dep+1].v[++rn].v=td[dep].v[i].v; if(rn!=mid+1) td[dep+1].sum[rn]=td[dep+1].sum[rn-1]; td[dep+1].sum[rn]+=td[dep].v[i].v; } } build(l,mid,dep+1); build(mid+1,r,dep+1); } int query(int a,int b,int k,int l,int r,int dep) { int mid=(l+r)>>1,ans,yy; if(a==b)return td[dep].v[a].v; int lx,rx=td[dep].num[b],sub,sl,sr; lx=(a<=l)?0:td[dep].num[a-1]; sub=rx-lx; if(sub>=k) return query(l+lx,l+rx-1,k,l,mid,dep+1); else { sl=a-l-lx; sr=b-l-rx; ans=(lx==0)?0:td[dep+1].sum[l+lx-1]; yy=(rx==0)?0:td[dep+1].sum[l+rx-1]; return yy-ans+query(mid+1+sl,mid+1+sr,k-sub,mid+1,r,dep+1); } } int find(int v,int n,int flag) { int start=0,end=n+1,mid; while(1) { mid=(start+end)>>1; if(start==mid)break; if(flag) { if(td[1].v[mid].dul<v) start=mid; else end=mid; } else { if(td[1].v[mid].dul>v) end=mid; else start=mid; } } return start+flag; } int main() { int n,i,cnt,m,l,r,k; freopen("in.in","r",stdin); freopen("out.out","w",stdout); while(scanf("%d",&n)!=EOF) { for(i=1,cnt=0;i<=n;i++){ ++cnt; scanf("%d%d",&data[cnt].dul,&data[cnt].v); if(data[cnt].v<=0) cnt--; } if(cnt>0){ sort(data+1,data+cnt+1,cmp); for(i=1,pre[0]=0;i<=cnt;i++){ pre[i]=pre[i-1]+data[i].v; td[1].v[i].v=data[i].v; td[1].v[i].dul=data[i].dul; } sort(data+1,data+cnt+1,cmp_); build(1,cnt,1); } scanf("%d",&m); while(m--) { scanf("%d%d%d",&l,&r,&k); if(cnt<1) { printf("0\n"); continue; } l=find(l,cnt,1); r=find(r,cnt,0); if(l>cnt||l>r) { printf("0\n"); continue; } if(k>r-l+1) printf("%d\n",pre[r]-pre[l-1]); else printf("%d\n",query(l,r,k,1,cnt,1)); } printf("\n"); } return 0; }
//csu1080 主席树版代码
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 10010 #define FN 200010 int C[FN],L[FN],R[FN],sum[FN],T[N],tot,cnt; int build(int l,int r) { int mid=(l+r)>>1,rt=++tot; if(l==r) return rt; L[rt]=build(l,mid); R[rt]=build(mid+1,r); return rt; } int update(int rt,int p,int d,int v) { int newrt=++tot,root=newrt; int l=1,r=cnt,mid; C[newrt]=C[rt]+d; sum[newrt]=sum[rt]+v; while(l<r) { mid=(l+r)>>1; if(p<=mid) { L[newrt]=++tot; R[newrt]=R[rt]; newrt=L[newrt]; rt=L[rt];r=mid; } else { R[newrt]=++tot;L[newrt]=L[rt]; newrt=R[newrt];rt=R[rt];l=mid+1; } C[newrt]=C[rt]+d;sum[newrt]=sum[rt]+v; } return root; } int query(int rt1,int rt2,int k) { int l=1,r=cnt,mid,ans=0; while(l<r) { mid=(l+r)>>1; if(C[L[rt2]]-C[L[rt1]]>=k) rt2=L[rt2],rt1=L[rt1],r=mid; else{ ans+=sum[L[rt2]]-sum[L[rt1]]; k-=C[L[rt2]]-C[L[rt1]]; rt1=R[rt1];rt2=R[rt2];l=mid+1; } } return ans+sum[rt2]-sum[rt1]; } struct node { int dul,v,sd; }data[N]; bool cmp1(node a,node b){ return a.v>b.v; } bool cmp2(node a,node b){ return a.dul<b.dul; } int find(int v,int n,int flag) { int start=0,end=n+1,mid; while(1) { mid=(start+end)>>1; if(start==mid)break; if(flag) { if(data[mid].dul<v) start=mid; else end=mid; } else { if(data[mid].dul>v) end=mid; else start=mid; } } return start+flag; } int p[N]; int main() { int i,m,k,a,b,n; while(scanf("%d",&n)!=EOF) { tot=cnt=0; for(i=1;i<=n;i++) { ++cnt; scanf("%d%d",&data[cnt].dul,&data[cnt].v); if(data[cnt].v<=0) --cnt; } if(cnt){ sort(data+1,data+cnt+1,cmp1); for(i=1;i<=cnt;i++) data[i].sd=i; sort(data+1,data+cnt+1,cmp2); for(i=1;i<=cnt;i++) p[i]=p[i-1]+data[i].v; T[0]=build(1,cnt); for(i=1;i<=cnt;i++) T[i]=update(T[i-1],data[i].sd,1,data[i].v); } scanf("%d",&m); while(m--) { scanf("%d%d%d",&a,&b,&k); if(cnt<1) { printf("0\n"); continue; } a=find(a,cnt,1); b=find(b,cnt,0); if(a>cnt||a>b) { printf("0\n"); continue; } if(k>=b-a+1) printf("%d\n",p[b]-p[a-1]); else printf("%d\n",query(T[a-1],T[b],k)); } printf("\n"); } return 0; }