【分块】bzoj3196 Tyvj 1730 二逼平衡树

分块 或 树套树。

在每个块中维护一个有序表,查询时各种二分,全都是分块的经典操作,就不详细说了。

块的大小定为sqrt(n*log2(n))比较快。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 int sum,sz,l[400],r[400],num[51001],a[51001],b[51001],x,y,k,n,m,op,tmp[2000];
  7 void makeblock()
  8 {
  9     memcpy(b,a,sizeof(a));
 10     sz=sqrt((double)n*log2(n));
 11     for(sum=1;sum*sz<n;sum++)
 12       {
 13         l[sum]=(sum-1)*sz+1;
 14         r[sum]=sum*sz;
 15         for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
 16         sort(b+l[sum],b+r[sum]+1);
 17       }
 18     l[sum]=sz*(sum-1)+1; r[sum]=n;
 19     for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
 20 }
 21 inline void Update()
 22 {
 23     *lower_bound(b+l[num[x]],b+r[num[x]]+1,a[x])=y;
 24     sort(b+l[num[x]],b+r[num[x]]+1);
 25     a[x]=y;
 26 }
 27 inline void Rank()
 28 {
 29     int ans=0;
 30     if(num[x]+1>=num[y]) {for(int i=x;i<=y;i++) if(a[i]<k) ans++;}
 31     else
 32       {
 33         for(int i=x;i<=r[num[x]];i++) if(a[i]<k) ans++;
 34         for(int i=l[num[y]];i<=y;i++) if(a[i]<k) ans++;
 35         for(int i=num[x]+1;i<num[y];i++) ans+=lower_bound(b+l[i],b+r[i]+1,k)-(b+l[i]);
 36       }
 37     printf("%d\n",ans+1);
 38 }
 39 inline void Kth()
 40 {
 41     if(num[x]+1>=num[y])
 42       {
 43         int en=0;
 44         for(int i=x;i<=y;i++) tmp[++en]=a[i];
 45         sort(tmp+1,tmp+en+1);
 46         printf("%d\n",tmp[k]);
 47       }
 48     else
 49       {
 50         int L=0,R=1000000001;
 51         while(L!=R)
 52           {
 53             int mid=L+R>>1,cnt=0;
 54             for(int i=x;i<=r[num[x]];i++) if(a[i]<mid) cnt++;
 55             for(int i=l[num[y]];i<=y;i++) if(a[i]<mid) cnt++; //统计<mid的值数
 56             for(int i=num[x]+1;i<num[y];i++) cnt+=lower_bound(b+l[i],b+r[i]+1,mid)-(b+l[i]);
 57             if(cnt>=k) R=mid;
 58             else L=mid+1;
 59           }
 60         printf("%d\n",L-1);
 61       }
 62 }
 63 inline void Front()
 64 {
 65     int ans=-2147483647;int* p;
 66     if(num[x]+1>=num[y]) {for(int i=x;i<=y;i++) if(a[i]>ans && a[i]<k) ans=a[i];}
 67     else
 68       {
 69         for(int i=x;i<=r[num[x]];i++) if(a[i]>ans && a[i]<k) ans=a[i];
 70         for(int i=l[num[y]];i<=y;i++) if(a[i]>ans && a[i]<k) ans=a[i];
 71         for(int i=num[x]+1;i<num[y];i++)
 72           {
 73             p=lower_bound(b+l[i],b+r[i]+1,k);
 74             if(p!=b+l[i] && *(p-1)<k && *(p-1)>ans) ans=*(p-1);
 75           }
 76       }
 77     printf("%d\n",ans);
 78 }
 79 inline void Next()
 80 {
 81     int ans=2147483647;int* p;
 82     if(num[x]+1>=num[y]) {for(int i=x;i<=y;i++) if(a[i]<ans && a[i]>k) ans=a[i];}
 83     else
 84       {
 85         for(int i=x;i<=r[num[x]];i++) if(a[i]<ans && a[i]>k) ans=a[i];
 86         for(int i=l[num[y]];i<=y;i++) if(a[i]<ans && a[i]>k) ans=a[i];
 87         for(int i=num[x]+1;i<num[y];i++)
 88           {
 89             p=upper_bound(b+l[i],b+r[i]+1,k);
 90             if(p!=b+r[i]+1 && *p>k && *p<ans) ans=*p;
 91           }
 92       }
 93     printf("%d\n",ans);
 94 }
 95 int main()
 96 {
 97     scanf("%d%d",&n,&m);
 98     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
 99     makeblock();
100     for(int i=1;i<=m;i++)
101       {
102         scanf("%d%d%d",&op,&x,&y);
103         if(op==3) Update();
104         else
105           {
106               scanf("%d",&k);
107             if(op==1) Rank();
108             else if(op==2) Kth();
109             else if(op==4) Front();
110             else Next();
111           }
112       }
113     return 0;
114 }
时间: 2024-10-01 04:24:05

【分块】bzoj3196 Tyvj 1730 二逼平衡树的相关文章

【函数式权值分块】【分块】bzoj3196 Tyvj 1730 二逼平衡树

#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define N 50001 #define SQRT 227 int n,m,xs[N],ys[N],ks[N],op[N],en,ma[100001],en2,a[100001]; int num[N],l[SQRT],r[SQRT],sumv[SQRT],sum=1;//分块 int num2[100001],l2[

【带修莫队】【权值分块】bzoj3196 Tyvj 1730 二逼平衡树

这题用了三种算法写: 分块+二分:O(n*sqrt(n*log(n)) 函数式权值分块:O(n*sqrt(n)) 带修莫队+权值分块:O(n5/3) 结果……复杂度越高的实际上跑得越快……最后这个竟然进第一页了…… #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int f,C; inline void R(int &

Bzoj3196 Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3350  Solved: 1324 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行

【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树

线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> #define N 50010 #define INF 2147483647 using namespace std; using namespace __gnu_pb

[bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)

Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作 第二行有n个数,表示有序序列 下面有m行,opt表示操作标号 若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,

【BZOJ 3196】Tyvj 1730 二逼平衡树

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 842  Solved: 350 [Submit][Status] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继(后继定义为大于x,

BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )

这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<ios

[Tyvj 1730] 二逼平衡树

先来一发题面QwQ [TYVJ1730]二逼平衡树 Time Limit:2 s   Memory Limit:512 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行有n个数