BZOJ4923:[Lydsy1706月赛]K小值查询(Splay)

Description

维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作:
1 k,将序列a从小到大排序,输出a_k的值。
2 k,将所有严格大于k的数a_i减去k。

Input

第一行包含两个正整数n,m(1<=n,m<=100000),分别表示序列的长度和操作的个数。
第二行包含n个正整数a_1,a_2,...,a_n(1<=a_i<=10^9),分别表示序列中的每个元素。
接下来m行,每行两个正整数op(1<=op<=2),k,若op=1,则1<=k<=n;若op=2,则1<=k<=10^9;依次描述每个操作。

Output

输出若干行,对于每个询问输出一行一个整数,即第k小的值。

Sample Input

4 5
1 5 6 12
2 5
1 1
1 2
1 3
1 4

Sample Output

1
1
5
7

Solution

把数排个序然后建$Splay$,每次修改对值域为$[1,k]$中的不管,$[k+1,k\times 2]$中的拆出来改完了再暴力插回去,对于$[k\times 2+1,MAX]$中打标记。我也不知道为什么复杂度是对的。

以后别有事没事把标记下传到$0$点,修改着修改着$0$下标的值就不知道被修改成什么鬼畜的数了。

Code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #define N (100009)
  5 using namespace std;
  6 
  7 int n,m,opt,k,a[N];
  8 int Root,Father[N],Son[N][2];
  9 int Val[N],Size[N],Max[N],Add[N];
 10 
 11 int Get(int x) {return Son[Father[x]][1]==x;}
 12 
 13 void Pushup(int x)
 14 {
 15     Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;
 16     Max[x]=max(Val[x],max(Max[Son[x][0]],Max[Son[x][1]]));
 17 }
 18 
 19 int Build(int fa,int l,int r)
 20 {
 21     if (l>r) return 0;
 22     int mid=(l+r)>>1;
 23     Father[mid]=fa; Val[mid]=a[mid];
 24     Son[mid][0]=Build(mid,l,mid-1);
 25     Son[mid][1]=Build(mid,mid+1,r);
 26     Pushup(mid); return mid;
 27 }
 28 
 29 void Rotate(int x)
 30 {
 31     int wh=Get(x);
 32     int fa=Father[x],fafa=Father[fa];
 33     if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
 34     Father[fa]=x; Son[fa][wh]=Son[x][wh^1];
 35     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
 36     Father[x]=fafa; Son[x][wh^1]=fa;
 37     Pushup(fa); Pushup(x);
 38 }
 39 
 40 void Pushdown(int x)
 41 {
 42     if (Add[x]!=0)
 43     {
 44         if (Son[x][0])
 45         {
 46             Val[Son[x][0]]+=Add[x];
 47             Add[Son[x][0]]+=Add[x];
 48             Max[Son[x][0]]+=Add[x];
 49         }
 50         if (Son[x][1])
 51         {
 52             Val[Son[x][1]]+=Add[x];
 53             Add[Son[x][1]]+=Add[x];
 54             Max[Son[x][1]]+=Add[x];
 55         }
 56         Add[x]=0;
 57     }
 58 }
 59 
 60 void Push(int x)
 61 {
 62     if (Father[x]) Push(Father[x]);
 63     Pushdown(x);
 64 }
 65 
 66 void Splay(int x,int tar)
 67 {
 68     Push(x);
 69     for (int fa; (fa=Father[x])!=tar; Rotate(x))
 70         if (Father[fa]!=tar)
 71             Rotate(Get(fa)==Get(x)?fa:x);
 72     if (!tar) Root=x;
 73 }
 74 
 75 int Findkth(int x)
 76 {
 77     int now=Root;
 78     while (1)
 79     {
 80         Pushdown(now);
 81         if (Size[Son[now][0]]>=x) now=Son[now][0];
 82         else
 83         {
 84             x-=Size[Son[now][0]];
 85             if (x==1) {Splay(now,0); return Val[now];}
 86             x--; now=Son[now][1];
 87         }
 88     }
 89 }
 90 
 91 int Find(int x)
 92 {
 93     int now=Root,ans=0;
 94     while (1)
 95     {
 96         Pushdown(now);
 97         if (Max[Son[now][0]]>x) now=Son[now][0];
 98         else
 99         {
100             if (Val[now]>x) {Splay(now,0); return now;}
101             now=Son[now][1];
102         }
103     }
104 }
105 
106 int Pre(int x)
107 {
108     Splay(x,0);
109     x=Son[x][0];
110     while (Son[x][1]) x=Son[x][1];
111     return x;
112 }
113 
114 void Insert(int x)
115 {
116     int now=Root,fa=0;
117     while (1)
118     {
119         Pushdown(now);
120         if (!now)
121         {
122             Father[x]=fa;
123             Son[fa][Val[fa]<Val[x]]=x;
124             Max[x]=Val[x]; Size[x]=1;
125             Splay(x,0); return;
126         }
127         fa=now, now=Son[now][Val[now]<Val[x]];
128     }
129 }
130 
131 void DFS(int x,int k)
132 {
133     if (!x) return;
134     Pushdown(x);
135     DFS(Son[x][0],k); DFS(Son[x][1],k);
136     Father[x]=Son[x][0]=Son[x][1]=Size[x]=Max[x]=0;
137     Val[x]-=k; Insert(x);
138 }
139 
140 void Update(int k)
141 {
142     int x=Pre(Find(k)),y=Find(2*k);
143     Splay(x,0); Splay(y,x);
144     int s=Son[y][0]; Son[y][0]=Father[Son[y][0]]=0; 
145     DFS(s,k);
146     Splay(y,0);
147     x=Pre(Find(2*k)),y=n+2;
148     Splay(x,0); Splay(y,x);
149     if (!Son[y][0]) return;
150     Add[Son[y][0]]-=k; Val[Son[y][0]]-=k; Max[Son[y][0]]-=k;
151 }
152 
153 int main()
154 {
155     scanf("%d%d",&n,&m);
156     for (int i=2; i<=n+1; ++i)
157         scanf("%d",&a[i]);
158     a[1]=-2e9; a[n+2]=2e9; Max[0]=-2e9;
159     sort(a+1,a+n+3);
160     Root=Build(0,1,n+2);
161     for (int i=1; i<=m; ++i)
162     {
163         scanf("%d%d",&opt,&k);
164         if (opt==1) printf("%d\n",Findkth(k+1));
165         else Update(k);
166     }
167 }
posted @ 2019-01-19 11:29  Refun  阅读(390)  评论(0编辑  收藏  举报