线段树:HDU4217

给你一个N,K;然后又有K个数i;表示从1,2,3…N个数 经过K次操作,每次操作是去掉第i小的数。求所有去掉数的之和;
#include
const 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){ //单点询问 sum
if(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;

}

你可能感兴趣的:(线段树:HDU4217)