您的位置:首页 > 其它

Gym 100960G Youngling Tournament(splay)

2016-09-01 00:24 381 查看
Description
standard input/output
Statements

Yoda, the Grand Master of the Jedi Order, hit on the idea to hold a tournament among younglings. He has not chosen the date yet, but he has already decided on the format of the tournament.

There are N younglings studying in the Jedi Temple. Yoda can feel the Force inside younglings, moreover, he can represent the amount of the Force inside
i-th youngling as the number
fi.

Therefore, the format of the tournament is the following. At first, Yoda makes the children stand in a row in order of non-increasing
fi. Then, the first youngling in the row competes against all the others united together. The combat is based on lightsaber battle and is very spectacular. However, Yoda knows that
the result doesn't depend on anything but the Force inside competitors. The youngling wins if his amount of Force is not less than the total amount of the Force inside all his opponents. In that case, he is considered one of the winners. Otherwise, he loses.
Anyway, after that he is removed from the row, and the tournament continues. Again, the strongest (first in the row) youngling competes against all the others standing in the row in the same format, if he wins, he is also considered one of the winners. After
that he is removed and the tournament continues in the same format until there is only one child in the row. He becomes one of the winners automatically and the tournament finishes.

Yoda wants to know the total number of winners. However, as the tournament is postponed again and again, the amount of the Force inside the younglings changes from time to time. Help Yoda to compute the total number of winners after each change.

Input

The first line of input contains a single integer N, the number of younglings in the Jedi Temple (1 ≤ N ≤ 100 000).

The second line contains N integers
f1, f2, ..., fN the amount of the Force inside the younglings (1 ≤ fi ≤ 1012).

The third line of the input contains a single integer M, the number of changes in the Force amounts of students (0 ≤ M ≤ 50 000).

The next M lines contain information about the changes. The
i-th of these lines describes the
i-th change and contains two integers k and
fk * , which mean that the amount of the Force inside the
k-th youngling becomes equal to
fk *  (1 ≤ k ≤ N,
1 ≤ fk *  ≤ 1012).

Output

Print M + 1 lines, each of them containing a single integer.

On the first line, print the number of winners if the tournament was held before all the changes. On line
(i + 1) for all i > 0, print the number of winners if the tournament was held after the first
i changes.

Sample Input

Input
3
2 1 3
3
1 3
2 7
3 5


Output
3
2
3
2


Input
7
2 14 14 15 5 2 5
5
5 2
4 12
5 4
3 10
7 9


Output
4
3
3
3
3
4


题意:给n个数,m次修改操作,每次把一个数换成另一个数,每次修改后问将原序列从小到大排序后,不小于它前边所有数个数有多少个。

分析:很显然这种数最多有log(10^12)个,于是我们可以用splay维护这个序列,然后每次在splay中查找符合条件的数,splay中最左边的数必定符合条件,设以它开始的前缀和为v,那么下一个符合条件的数至少为v,这样继续在splay中查找,每个询问最多找不到40次。

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
#include <unordered_map>
#define INF 21474836470000
#define eps 1e-9
#define MOD 1000000007
#define MAXN 150010
using namespace std;
typedef long long ll;
int pre[MAXN],ch[MAXN][2],root,tot,n,m,q;
ll sum[MAXN],key[MAXN],a[MAXN],b[MAXN],Max[MAXN];
void NewNode(int &r,int father,ll k)
{
r = ++tot;
pre[r] = father;
Max[r] = key[r] = sum[r] = k;;
ch[r][0] = ch[r][1] = 0;
}
void push_up(int r)
{
sum[r] = sum[ch[r][0]] + sum[ch[r][1]] + key[r];
Max[r] = max(key[r],max(Max[ch[r][0]],Max[ch[r][1]]));
}
void Rotate(int x,int kind)
{
int y = pre[x];
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
push_up(y);
}
void Splay(int r,int goal)
{
while(pre[r] != goal)
{
if(pre[pre[r]] == goal) Rotate(r,ch[pre[r]][0] == r);
else
{
int y = pre[r];
int kind = ch[pre[y]][0] == y;
if(ch[y][kind] == r)
{
Rotate(r,!kind);
Rotate(r,kind);
}
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
push_up(r);
if(goal == 0) root = r;
}
int Find(int r,ll val)
{
if(r == 0) return 0;
if(Max[ch[r][0]] >= val) return Find(ch[r][0],val);
if(key[r] >= val) return r;
return Find(ch[r][1],val);
}
void Insert(int &r,ll val)
{
if(r == 0)
{
NewNode(r,0,val);
return;
}
if(val <= key[r])
{
if(!ch[r][0]) NewNode(ch[r][0],r,val);
else Insert(ch[r][0],val);
}
else
{
if(!ch[r][1]) NewNode(ch[r][1],r,val);
else Insert(ch[r][1],val);
}
push_up(r);
}
void Init()
{
root = tot = 0;
for(int i = 1;i <= n;i++)
{
Insert(root,b[i]);
if(i % 178 == 0) Splay(tot,0);
}
}
void Delete_pos(int x)//删除节点
{
Splay(x,0);
int tmp = ch[root][1];
if(!tmp)
{
root = ch[root][0];
pre[root] = 0;
}
else
{
while(ch[tmp][0]) tmp = ch[tmp][0]; ;//找到根节点右子树最小元素(往左找)
Splay(tmp,root);//将它移到根节点的右儿子
ch[tmp][0] = ch[root][0];//将后继作为根节点,根节点删除。
pre[ch[root][0]] = tmp;
pre[tmp] = 0;
root = tmp; //后继成为根节点
push_up(root);
}
}
void got()
{
int tmp = root;
while(ch[tmp][0]) tmp = ch[tmp][0];
Splay(tmp,0);
int ans = 1,temp;
do
{
temp = Find(ch[root][1],key[root] + sum[ch[root][0]]);
if(temp > 0)
{
Splay(temp,0);
if(key[root] >= sum[ch[root][0]]) ans++;
}
}while(temp > 0);
printf("%d\n",ans);
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i++) scanf("%lld",&b[i]);
Init();
got();
scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
int pos;ll val;
scanf("%d%lld",&pos,&val);
Delete_pos(Find(root,b[pos]));
b[pos] = val;
Insert(root,val);
got();
if(i % 280 == 0) Splay(tot,0);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: