题目的大概意思是有1,2,3,,,N的N个数,每次去掉第ki小的数,经过k次操作,求去掉的数的总和。
思路:线段树,由于每个元素所代表的区间的数都是有序的,每个元素只需记录相应区间的数的个数即可。注用long long.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 262144 struct node { __int64 len,num; }setree[maxn<<2]; __int64 ans; void build(__int64 l,__int64 r,__int64 rt) { setree[rt].len=r-l+1; if(l==r){ setree[rt].num=l; return; } int m=(l+r)>>1; build(lson); build(rson); } void pushup(__int64 rt) { setree[rt].len=setree[rt<<1].len+setree[rt<<1|1].len; } void update(__int64 l,__int64 r,__int64 rt,__int64 k) { if(l==r){ setree[rt].len=0; ans+=setree[rt].num; return; } __int64 m=(l+r)>>1; if(k<=setree[rt<<1].len) update(lson,k); else update(rson,k-setree[rt<<1].len); pushup(rt); } int main() { __int64 n,op,cas=1,t; scanf("%I64d",&t); while(t--){ scanf("%I64d%I64d",&n,&op); build(1,n,1); ans=0; while(op--){ __int64 k; scanf("%I64d",&k); update(1,n,1,k); } printf("Case %I64d: %I64d\n",cas++,ans); } }