C - Serge and Dining Room(思维+权值线段树)

https://codeforces.com/contest/1179/problem/C


思路:

思考x作为答案时候,条件是啥。

就是大于等于x的商品个数 > 大于等于x的小朋友的钱的个数。

那么对于这一单点点。维护好之后就是找后缀>0的最后位置。

一个做法就是转化成维护前缀和区间修改。然后查区间最值来找到这个位置。

插眼:cf393E

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e6+100;
typedef int LL;
void read() {}
template<typename T,typename... T2>inline void read(T &x,T2 &... oth) { x=0;int ch=getchar(),f=0;while(ch<'0'||ch>'9') { if (ch=='-') f=1;ch=getchar();}while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}if(f)x=-x;read(oth...);}
inline void write(int a) {if(a<0) putchar('-'),a=-a;if(a>=10)write(a/10);putchar(a%10+48);}
LL a[maxn],b[maxn];
struct Tree{
    LL l,r,maxval,tag;
}tree[maxn<<2];
inline void push_up(LL p){
     tree[p].maxval=max(tree[p<<1].maxval,tree[p<<1|1].maxval);
}
inline void addtag(LL p,LL d){
     tree[p].maxval+=d;
     tree[p].tag+=d;
}
inline void push_down(LL p){
     if(tree[p].tag){
        addtag(p<<1,tree[p].tag);
        addtag(p<<1|1,tree[p].tag);
        tree[p].tag=0;
     }
}
inline void build(LL p,LL l,LL r){
     tree[p].l=l;tree[p].r=r;tree[p].maxval=0;tree[p].tag=0;
     if(l==r){return;}
     LL mid=(l+r)>>1;
     build(p<<1,l,mid);build(p<<1|1,mid+1,r);
     push_up(p);
}
inline void modify(LL p,LL l,LL r,LL d){
     if(l<=tree[p].l&&r>=tree[p].r){
        addtag(p,d);
        return;
     }
     push_down(p);
     LL mid=(tree[p].l+tree[p].r)>>1;
     if(l<=mid) modify(p<<1,l,r,d);
     if(r>mid) modify(p<<1|1,l,r,d);
     push_up(p);
}
inline LL query(LL p){
   if(tree[p].l==tree[p].r){
      return tree[p].l;
   }
   push_down(p);
   LL mid=(tree[p].l+tree[p].r)>>1;
   if(tree[p<<1|1].maxval>0){///先看右儿子
      return query(p<<1|1);
   }
   else if(tree[p<<1].maxval>0) return query(p<<1);///再左边儿子
   else return -1;
}
int main(void){
   LL n,m;read(n);read(m);
   build(1,0,1000000);
   for(LL i=1;i<=n;i++){
       read(a[i]);
       modify(1,1,a[i],1);
   }
   for(LL i=1;i<=m;i++){
       read(b[i]);
       modify(1,1,b[i],-1);
   }
   LL Q;read(Q);
   while(Q--){
       LL op,pos,val;read(op);read(pos);read(val);
       if(op==1){
          modify(1,1,a[pos],-1);
          a[pos]=val;
          modify(1,1,a[pos],1);
       }
       else if(op==2){
          modify(1,1,b[pos],1);
          b[pos]=val;
          modify(1,1,b[pos],-1);
       }
       write(query(1));
       printf("\n");
   }
   return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值