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
1 5 6 12
2 5
1 1
1 2
1 3
1 4
Sample Output
1
1
5
7
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 }