time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Serge came to the school dining room and discovered that there is a big queue here. There are mm pupils in the queue. He's not sure now if he wants to wait until the queue will clear, so he wants to know which dish he will receive if he does. As Serge is very tired, he asks you to compute it instead of him.
Initially there are nn dishes with costs a1,a2,…,ana1,a2,…,an. As you already know, there are the queue of mm pupils who have b1,…,bmb1,…,bm togrogs respectively (pupils are enumerated by queue order, i.e the first pupil in the queue has b1b1 togrogs and the last one has bmbm togrogs)
Pupils think that the most expensive dish is the most delicious one, so every pupil just buys the most expensive dish for which he has money (every dish has a single copy, so when a pupil has bought it nobody can buy it later), and if a pupil doesn't have money for any dish, he just leaves the queue (so brutal capitalism...)
But money isn't a problem at all for Serge, so Serge is buying the most expensive dish if there is at least one remaining.
Moreover, Serge's school has a very unstable economic situation and the costs of some dishes or number of togrogs of some pupils can change. More formally, you must process qq queries:
Nobody leaves the queue during those queries because a saleswoman is late.
After every query, you must tell Serge price of the dish which he will buy if he has waited until the queue is clear, or −1−1 if there are no dishes at this point, according to rules described above.
Input
The first line contains integers nn and mm (1≤n,m≤300 0001≤n,m≤300 000) — number of dishes and pupils respectively. The second line contains nnintegers a1,a2,…,ana1,a2,…,an (1≤ai≤1061≤ai≤106) — elements of array aa. The third line contains mm integers b1,b2,…,bmb1,b2,…,bm (1≤bi≤1061≤bi≤106) — elements of array bb. The fourth line conatins integer qq (1≤q≤300 0001≤q≤300 000) — number of queries.
Each of the following qq lines contains as follows:
Output
For each of qq queries prints the answer as the statement describes, the answer of the ii-th query in the ii-th line (the price of the dish which Serge will buy or −1−1 if nothing remains)
Examples
input
Copy
1 1 1 1 1 1 1 100
output
Copy
100
input
Copy
1 1 1 1 1 2 1 100
output
Copy
-1
input
Copy
4 6 1 8 2 4 3 3 6 1 5 2 3 1 1 1 2 5 10 1 1 6
output
Copy
8 -1 4
Note
In the first sample after the first query, there is one dish with price 100100 togrogs and one pupil with one togrog, so Serge will buy the dish with price 100100 togrogs.
In the second sample after the first query, there is one dish with price one togrog and one pupil with 100100 togrogs, so Serge will get nothing.
In the third sample after the first query, nobody can buy the dish with price 88, so Serge will take it. After the second query, all dishes will be bought, after the third one the third and fifth pupils will by the first and the second dishes respectively and nobody will by the fourth one.
点我传送
给出a序列为各种食物的价格,b序列为小朋友拥有的钱,小朋友依次购买食物,每个人都买自己能买的起的最贵的食物,买不起就离开队伍。给出q次操作,操作1是修改食物的价格,操作2是修改小朋友的钱,每次操作后询问当小朋友买完之后,能买到的最贵的食物的价格是多少,没有食物了就输出-1。
对于每个食物,在[ 1,ai ]范围上都加上1 ,对于每个小朋友,在 [ 1,bi ]上都减去1.
每个询问实际上就是在寻找这个前缀和出现大于0的最大的位置。
那么在线段树查询操作时,如果发现右子树存在这样的解那么肯定就是优先右子树;否则才考虑左子树。
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
int n,m;
const int N=6e5+5;
int a[N],b[N],v[3*N];
int sum;
struct Que
{
int ty,p,val;
}q[N];
LL lazy[N << 2]; //lazy用来记录该节点的每个数值应该加多少
struct Tree
{
int l, r;
LL sum;
int mid()
{
return (l + r) >> 1;
}
}tree[N<<2]; //tree[].l, tree[].r分别表示某个节点的左右区间,这里的区间是闭区间
void PushUp(int rt)
{
tree[rt].sum = max(tree[rt << 1].sum , tree[rt << 1 | 1].sum);
}
void PushDown(int rt,int m)
{
if (lazy[rt]!=0)
{
lazy[rt << 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
tree[rt << 1].sum += lazy[rt];
tree[rt << 1 | 1].sum += lazy[rt];
lazy[rt] = 0;
}
}
void build(int l, int r, int rt)
{
tree[rt].l = l;
tree[rt].r = r;
lazy[rt] = 0;
if (l == r)
{
tree[rt].sum = 0;
return;
}
int m = tree[rt].mid();
build(l, m, (rt << 1));
build(m + 1, r, (rt << 1 | 1));
PushUp(rt);
}
void update(int c, int l, int r, int rt)//表示对区间[l,r]内的每个数均加c,rt是根节点
{
if (tree[rt].l == l&&tree[rt].r==r)
{
lazy[rt] += c;
tree[rt].sum += c;
return;
}
if (tree[rt].l == tree[rt].r)return;
int m = tree[rt].mid();
PushDown(rt, tree[rt].r - tree[rt].l + 1);
if (r <= m)update(c, l, r, rt << 1);
else if (l > m)update(c, l, r, rt << 1 | 1);
else
{
update(c, l, m, rt << 1);
update(c, m + 1, r, rt << 1 | 1);
}
PushUp(rt);
}
LL Query(int l, int r, int rt)
{
//printf("**%d %d sum:%d\n",tree[rt].l,tree[rt].r,tree[rt].sum);
if (tree[rt].l==tree[rt].r)
{
return tree[rt].l;
}
int m = tree[rt].mid();
PushDown(rt, tree[rt].r - tree[rt].l + 1);
if(tree[rt<<1|1].sum>0)return Query(m+1,r,rt<<1|1);
else return Query(l,m,rt<<1);
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
v[++sum]=a[i];
}
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
v[++sum]=b[i];
}
int Q;
scanf("%d",&Q);
for(int i=1;i<=Q;i++)
{
scanf("%d %d %d",&q[i].ty,&q[i].p,&q[i].val);
v[++sum]=q[i].val;
}
sort(v+1,v+1+sum);
sum=unique(v+1,v+1+sum)-v-1;
for(int i=1;i<=n;i++)a[i] = lower_bound(v+1,v + sum+1,a[i]) -v;
for(int i=1;i<=m;i++)b[i] = lower_bound(v+1,v + sum+1,b[i]) -v;
for(int i=1;i<=Q;i++)q[i].val= lower_bound(v+1,v + sum+1,q[i].val) -v;
build(1,sum,1);
for(int i=1;i<=n;i++)update(1,1,a[i],1);
for(int i=1;i<=m;i++)update(-1,1,b[i],1);
//printf("q1:%d\n",Query(1,1,1));
for(int i=1;i<=Q;i++)
{
if(q[i].ty==1)
{
update(-1,1,a[q[i].p],1);
a[q[i].p]=q[i].val;
update(1,1,a[q[i].p],1);
}
else
{
update(1,1,b[q[i].p],1);
b[q[i].p]=q[i].val;
update(-1,1,b[q[i].p],1);
}
if(tree[1].sum<=0)printf("-1\n");
else printf("%d\n",v[Query(1,sum,1)]);
}
return 0;
}