hdu5412CRB and Queries

 动态修改求区间K大。

整体二分是一个神奇的东西: http://www.cnblogs.com/zig-zag/archive/2013/04/18/3027707.html

 入门:

一般的主席树都挂了,而且又难写。

南神的分析:http://blog.csdn.net/hdu2014/article/details/47834431 ORZ

然后对着板子写了一份:

          1 #include<iostream>

  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #define maxn 450000
  7 #define inf 2000000000
  8 typedef long long ll;
  9 
 10 using namespace std;
 11 struct query
 12 {
 13     int x,y,k,s,tp,cur;
 14 }q[maxn],q1[maxn],q2[maxn];
 15 int a[maxn],ans[maxn],tmp[maxn],t[maxn];
 16 int n,m,num,cnt;
 17 
 18 void add(int x,int y)
 19 {
 20     for (int i=x;i<=n;i+=i&(-i)) t[i]+=y;
 21 }
 22 int ask(int x)
 23 {
 24     int s=0;
 25     for (int i=x;i>0;i-=i&(-i)) s+=t[i];
 26     return s;
 27 }
 28 
 29 void divide(int head,int tail,int l,int r)
 30 {
 31     if (head>tail) return;
 32     if (l==r)
 33     {
 34         for (int i=head;i<=tail;i++)
 35             if (q[i].tp==3) ans[q[i].s]=l;
 36         return;
 37     }
 38     int mid=(l+r)>>1;
 39     for (int i=head;i<=tail;i++)
 40     {
 41         if (q[i].tp==1&&q[i].y<=mid) add(q[i].x,1);
 42         else
 43         if (q[i].tp==2&&q[i].y<=mid) add(q[i].x,-1);
 44         else
 45         if (q[i].tp==3) tmp[i]=ask(q[i].y)-ask(q[i].x-1);
 46     }
 47 
 48     for (int i=head;i<=tail;i++)
 49     {
 50         if (q[i].tp==1&&q[i].y<=mid) add(q[i].x,-1);
 51         else
 52         if (q[i].tp==2&&q[i].y<=mid) add(q[i].x,1);
 53     }
 54 
 55     int l1,l2;
 56     l1=l2=0;
 57     for (int i=head;i<=tail;i++)
 58     if (q[i].tp==3)
 59     {
 60        if (q[i].cur+tmp[i]>q[i].k-1) q1[++l1]=q[i];
 61        else
 62        {
 63            q[i].cur+=tmp[i];
 64            q2[++l2]=q[i];
 65        }
 66     }
 67     else
 68     {
 69         if (q[i].y<=mid) q1[++l1]=q[i];
 70         else q2[++l2]=q[i];
 71     }
 72 
 73     for (int i=1;i<=l1;i++) q[head+i-1]=q1[i];
 74     for (int i=1;i<=l2;i++) q[head+i+l1-1]=q2[i];
 75     divide(head,head+l1-1,l,mid);
 76     divide(head+l1,tail,mid+1,r);
 77 }
 78 
 79 int main()
 80 {
 81     while (scanf("%d",&n)!=EOF)
 82     {
 83         for (int i=0;i<=n;i++) t[i]=0;
 84         memset(q,0,sizeof(q));
 85         memset(q1,0,sizeof(q1));
 86         memset(q2,0,sizeof(q2));
 87 
 88         num=cnt=0;
 89         for (int i=1;i<=n;i++)
 90         {
 91             scanf("%d",&a[i]);
 92             q[++num].x=i,q[num].y=a[i];
 93             q[num].tp=1;q[num].s=0;
 94         }
 95         int ss,x,y,z;
 96         scanf("%d",&m);
 97         for (int i=1;i<=m;i++)
 98         {
 99             scanf("%d",&ss);
100             if (ss==2)
101             {
102                 scanf("%d%d%d",&x,&y,&z);
103                 q[++num].x=x,q[num].y=y,q[num].k=z;
104                 q[num].tp=3;q[num].s=++cnt;
105             }
106             else
107             {
108                 scanf("%d%d",&x,&y);
109                 q[++num].x=x;
110                 q[num].y=a[x];
111                 q[num].tp=2;q[num].s=0;
112                 q[++num].x=x,q[num].y=y;
113                 q[num].tp=1,q[num].s=0;
114                 a[x]=y;
115             }
116         }
117 
118         divide(1,num,0,inf);
119         for (int i=1;i<=cnt;i++)
120             printf("%d\n",ans[i]);
121     }
122     return 0;

123 } 

 2s左右。

posted on 2015-09-02 00:41  forgot93  阅读(142)  评论(0编辑  收藏  举报

导航