2019 ICPC Asia Jakarta Regional Contest G. Performance Review (线段树)
题意:
一个公司有n个人,每年有若干个人应聘,每次都会开除排名倒数的若干个人并将所有应聘的人招进公司,接下来有q次修改,每次可以修改每年应聘人的能力值,并询问1号员工能否在m年后仍然在公司
思路:
预处理,b[i]表示 有多少个元素比第一个元素小 。对b[]建立线段树。每次询问则是区间更新,判断sum[1]>=0则输出1,否则0
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1e9;
const int maxn=3e5+5;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
ll n,m,q,lazy[maxn<<2],sum[maxn<<2],a[maxn],b[maxn];
vector<ll>p[maxn];
void pushdown(int rt,int l,int r){
if(lazy[rt]){
sum[rt<<1]+=lazy[rt];
sum[rt<<1|1]+=lazy[rt];
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void build(int rt,int l,int r){
if(l==r){
sum[rt]=b[l];
lazy[rt]=0;
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
sum[rt]=min(sum[rt<<1],sum[rt<<1|1]);
}
void update(int rt,int l,int r,int x,int y,ll val){
//if(x>y)return;
if(x<=l&&r<=y){
sum[rt]+=val;
lazy[rt]+=val;
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
if(x<=mid)
update(lson,x,y,val);
if(y>mid)
update(rson,x,y,val);
sum[rt]=min(sum[rt<<1],sum[rt<<1|1]);
}
int main(){
scanf("%lld%lld%lld",&n,&m,&q);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(i>=2&&a[i]<a[1])b[0]++;//b[i]表示 有多少个元素比第一个元素小
}
for(int i=1,k,tmp=0;i<=m;i++){
scanf("%d",&k);
b[i]=b[i-1]-k+tmp;//tmp表示上一次替换有多少个元素比第一个元素小
tmp=0;
while(k--){
ll x;
scanf("%lld",&x);
p[i].push_back(x);
if(x<a[1])tmp++;
}
}
build(1,1,m);
while(q--){
int op,id;
ll x;
scanf("%d%d%lld",&id,&op,&x);
if(id<m&&p[id][op-1]>a[1]&&a[1]>x)
update(1,1,m,id+1,m,1);
else if(id<m&&p[id][op-1]<a[1]&&a[1]<x)
update(1,1,m,id+1,m,-1);
if(sum[1]>=0)printf("1\n");
else printf("0\n");
p[id][op-1]=x;
}
}