hdu 4006 The kth great number 很复杂的线段树,至少对于我来说,但也学会了很多!!!!!!!!!!

这道题是网络预选赛上做的,当时就是超时,后来知道是线段树,从时间复杂度来说用线段树先是将所用的点记录然后nlog的快排,之后查询就是logn了,软和不用线段树,之后的查询是On的复杂度,要是来一堆大数据那就必然超时了

废话不多说了,先将记录的所用点排序,在离散化,建树,将数据记录在最低叶上,再用num记录区间内点的数量,在从后往前搜,遇见I就将对应点之前的区间num减1,遇见Q就搜索K大的数!!!!!!!!!!

 #include<iostream>
using namespace std;
#include<algorithm> 
int size;
struct operaten//定义操作数 
{
    char cha;
    int num;
}ope[1000010];
int num[1000010];
int ans[1000010];
int po;
struct Curnode//当前节点 
{
    int big;
    int bnum;
}curnode[1000010];
struct node//定义树 
{
     int ll;
     int rr;
     int big;
     int bnum;
}a[3000010];
void init(int n)//离散化 
{
     size=1;
     curnode[size].big=num[1];
     curnode[size].bnum=1;
     for(int i=2;i<=n;i++)
     {
          if(num[i]==curnode[size].big)
          {
                curnode[size].bnum++;
          }
          else
          {
                curnode[++size].big=num[i];
                curnode[size].bnum=1;
          }
     }
     return ;
}
void build(int left,int right,int p)//建树 
{
     a[p].ll=left;// 两个子叶表示区间 
     a[p].rr=right;//
     if(left==right)
     {
          a[p].big=curnode[left].big;
          a[p].bnum=curnode[left].bnum;
          return ;
     }
     int mid=(left+right)/2;
     build(left,mid,2*p);
     build(mid+1,right,2*p+1);//有规矩,这里的mid必须加一 ,注意得到mid的除法模式 
     a[p].bnum=a[p*2].bnum+a[p*2+1].bnum;
     a[p].big=-1;
     return ;
}
void updata(int delnum,int p)
{
     a[p].bnum--;
     if(a[p].ll==a[p].rr)
     return;
     int mid=(a[p].ll+a[p].rr)/2;
     if(curnode[mid].big>=delnum)//注意啊!!涉及到这个等号都要向左面 
     {
        updata(delnum,p*2);
     }
     else
     updata(delnum,p*2+1);
     return ;
}
void query(int k,int p)
{
     if(a[p].ll==a[p].rr)
     {
        ans[po++]=curnode[a[p].ll].big;
        return ;
     }
     if(a[p*2+1].bnum>=k)
     {
        query(k,p*2+1);
     }
     else
     query(k-a[p*2+1].bnum,p*2);
     return ;
}
int main()
{
     int n,k;
     char ch;
     int temp;
     while(scanf("%d%d",&n,&k)!=EOF)
     {
          po=1;
          int t=1;
          for(int i=1;i<=n;i++)
          {
               getchar();
               scanf("%c",&ch);
               if(ch=='I')
               {
                    scanf("%d",&temp);
                    ope[i].num=temp;
                    ope[i].cha='I';
                    num[t++]=temp;
               }
               else
               {
                    ope[i].num=-1;
                    ope[i].cha='Q';
               }
          }
          sort(num+1,num+t);
          init(t-1);
          build(1,size,1);
          for(int i=n;i>=1;i--)
          {
               if(ope[i].cha=='I')
               {
                    updata(ope[i].num,1);       
               }
               if(ope[i].cha=='Q')
               {
                    query(k,1);
               }
          }
          for(int i=po-1;i>=1;i--)
          printf("%d\n",ans[i]);
     }
     return 0;
}


   
   
   
   
    
 
 
 
 

你可能感兴趣的:(hdu 4006 The kth great number 很复杂的线段树,至少对于我来说,但也学会了很多!!!!!!!!!!)