hdu 2852

来源:互联网 发布:苍老师高清种子源码 编辑:程序博客网 时间:2024/05/23 11:00

题意 输入0 a 把a压入容器 输入1 a 把a从容器中删除 输入 2 a b 输出大于a的第b个数
两个月前刚开始做题,啥也不会的时候,好像刚自学着搜索,跟着大佬们去上了一节树状数组,那时候居然没有一脸蒙蔽 真是佩服自己,而且后来居然还回去好好看了树状数组的博客,太佩服自己了,现在看着 觉得树状数组的操作比线段树要简单很多。但是如果要用线段树实现树状数组的功能却非常麻烦。树状数组的初始化,更新,求和,用来维护的数组储存的时候每一段区间的和 一个很神奇的东西 #define Lowbit ( (x)&(-x) ) 有了它你就能创建一棵平衡二叉树。每次都是合并同等高度的子树。
使得复杂度降得log(n)

#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define N 100010#define Lowbit(x) ((x)&(-x))int C[N];bool vis[N];void add(int x,int num) //加入元素num为1 删除元素 num为-1.{    while(x<N)    {        C[x]+=num;        x+=Lowbit(x); //开辟整个树状数组的空间    }}int Sum(int x){    int ans=0;    while(x>0)    {        ans+=C[x];        x-=Lowbit(x);  //利用树状数组的性质求和。每次都是移位的运算。    }                  //求的是区间和    return ans;}int binarysearch(int l,int k){    int mid,left,right,tmp;    left=l+1;   //查找的范围是从 l+1开始的 第k个存在的数    right=N-1;  //因为树状数组这种方法就是查找整个树状数组这个容器的所有数 所以 右边界是 N-1    if(Sum(right)-Sum(l)<k) return -1;  //首先判断的是整个树状数组的全部区间的存在个数是否满足 第k个 如果不满足 直接返回-1                                         //由于是用数组的下标来存储元素 如果这个元素存在这个容器里面    while(left<=right)                    //那么vis 就为1 而且 C[x]++;C这个数组下标是元素 存的是元素的个数    {                                     //再利用二分查找 使得查找降为log n 简直太聪明了        mid=(left+right)>>1;        tmp=Sum(mid)-Sum(l);          if(tmp==k)  //如果中点到左边界的里面存在数的个数刚刚好 那么就从中点作为右边界开始找就行。        {            if(vis[mid])     //如果二分的中点刚好是所求点 那么判断他是否存在就行                return mid;  //如果不存在 因为 Sum(mid) 找的数肯定不会超过mid 把右边界更新为mid-1                              //就行             right=mid-1;               //这里的二分和我前天晚上做的那个codeforces 很像 虽然我自己做出来了,这里居然没认出来 好丢人呐。。        }        else if(tmp>k)        {                      //如果里面存在的数比要找的多 那么也是首先判断中点是不是            if(Sum(mid-1)-Sum(l)<k) return mid; //相当于顺便判断了 vis[mid]==1            right = mid -1;             }        else{            left=mid+1;        //如果里面存在的数比要找的少 那么肯定不在这个区间 所以把左边界更新为mid+1        }    }    return -1;}int main(){    int p,n,m,T,e,a,k,l,r,mid;    while(~scanf("%d",&T))    {        memset(C,0,sizeof(C));        memset(vis,0,sizeof(vis));        while(T--)        {            scanf("%d",&p);            switch(p)            {                case 0:                scanf("%d",&e);                add(e,1);   //初始化树状数组                vis[e]=1;                break;                case 1:                scanf("%d",&e);                m=Sum(e)-Sum(e-1);                if(!m) printf("No Elment!\n");                else add(e,-1);                if(m==1) vis[e]=0;                break;                case 2:                scanf("%d%d",&a,&k);                m=binarysearch(a,k);                if(m==-1)                    printf("Not Find!\n");                else                    printf("%d\n",m);                break;            }        }    }}
0 0