1. 程式人生 > >hdu 4006 The kth great number 很複雜的線段樹,至少對於我來說,但也學會了很多!!!!!!!!!!

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;
}