线段树:HDU4217

来源:互联网 发布:php sha1加密 编辑:程序博客网 时间:2024/06/01 08:54
给你一个N,K;然后又有K个数i;表示从1,2,3…N个数 经过K次操作,每次操作是去掉第i小的数。求所有去掉数的之和;
#includeconst int MAXN=262144;int tree[MAXN<<1];int pos;void build(int l,int r,int rt){    tree[rt]=r-l+1;//表示节点含有的数据个数    if(r==l)        return ;    int m=(r+l)/2;    build(l,m,rt*2);    build(m+1,r,rt*2+1);}void update(int p,int l,int r,int rt){    tree[rt]--;//更新节点的数的个数    if(r==l)    {        pos=l;//此时的pos代表第几个最小值        return ;    }    int m=(r+l)/2;    if(p<=tree[rt*2])//搜索所需改变的节点        update(p,l,m,rt*2);    else    {        p-=tree[rt*2];        update(p,m+1,r,rt*2+1);    }}int main(){    int t,k,n,ks,tn=1;     __int64 sum;scanf("%d",&t);    while(t--)    {        sum=0;        scanf("%d%d",&n,&k);        build(1,n,1);        for(int i=0;i        {            scanf("%d",&ks);            update(ks,1,n,1);            sum+=pos;        }        printf("Case %d: %I64d\n",tn++,sum);    }    return 0;}////////////////////////////////////////////////////////#include#include#include#include#include#define N  300000#define M 2000100#define inf64 0x7ffffff#define inf 0x7ffffff#define ll __int64#define L(x) (x<<1)#define R(x) (x<<1|1)#define Mid(x,y) ((x+y)>>1)using namespace std;inline ll Min(ll a,ll b){return a>b?b:a;}inline ll Max(ll a,ll b){return a>b?a:b;}ll len,maxdeep,Query;struct node{ll l,r;ll sum;}tree[N*8];void build(ll l, ll r, ll id){tree[id].l = l; tree[id].r = r;if(l==r){tree[id].sum=1;return ;}ll mid = Mid(l,r);build(l,mid,L(id)); build(mid+1,r,R(id));tree[id].sum = tree[L(id)].sum + tree[R(id)].sum;}ll ans;void query(ll pos, ll id){ //单点询问 sumif(tree[id].l == tree[id].r){tree[id].sum = 0;ans+=tree[id].l ;return ;}if(pos> tree[L(id)].sum) query(pos-tree[L(id)].sum,R(id));if(pos<=tree[L(id)].sum) query(pos,L(id));tree[id].sum = tree[L(id)].sum + tree[R(id)].sum;}int main(){ll n,a,K,i;int T,Cas=1;scanf("%d",&T);while(T--){scanf("%I64d %I64d",&n,&K);build( 1, n, 1);ans=0;while(K--){scanf("%I64d",&a);query(a,1);}printf("Case %d: %I64d\n",Cas++,ans);}return 0;}**************************************************************************struct Node{  int left,right;//左右边界  int min,max;//该区间内的最小值,最大值};Node node[N*3];int a[N];//a[i]记录第i个位置上的数字void createTree(int L,int R,int id){      node[id].left = L;      node[id].right = R;   //叶子节点      if(node[id].left==node[id].right)     {       node[id].min = a[L];      node[id].max = a[L];       return;     }  int mid = (node[id].left+node[id].right)>>1;      //左子树    createTree(L,mid,2*id);   //右子树    createTree(mid+1,R,2*id+1);        node[id].min = Min(node[2*id].min,node[2*id+1].min);    node[id].max = Max(node[2*id].max,node[2*id+1].max);}int search(int L,int R,int id, int (*function)(int,int)){   if(node[id].left>=L&&node[id].right<=R)   return function(node[id].min,node[id].max);   int mid = (node[id].left+node[id].right)>>1;   if(R<=mid)//在左子树     return search(L,R,2*id,function);             if(L>mid)//位于右子树     return search(L,R,2*id+1,function);//分别位于左右子树   return function(search(L,mid,2*id,function),search(mid+1,R,2*id+1,function));}int main(){   int i,n,k;   scanf("%d%d",&n,&k);                for(i=1;i<=n;i++)       scanf("%d",&a[i]);   createTree(1,n,1);   int last = n-k+1;   for(i=1;i         printf("%d ", search(i,i+k-1,1,Min));        printf("%d\n",search(i,i+k-1,1,Min));       for(i=1;i             printf("%d ",search(i,i+k-1,1,Max));      printf("%d\n",search(i,i+k-1,1,Max));   return 0;}

原创粉丝点击