CF-1252G-Performance Review(思维+线段树)

题目链接https://codeforces.com/contest/1252/problem/G

题目大意:给出n个人,每个人有自己的能力值,第一个人表示P。然后给出m年,每年都有新人进入公司。每次都会先踢出新人数量的老人,提出的人都是能力最后的几位。然后加入新人。前一年的新人在下一年就变成了可以被踢出的老人了。

q次询问,询问不独立(这次询问对下次询问有影响)。

每次将第x年的第i个人的能力值变为z。问P是否最后还在公司中。

注意:每个人的能力值都不会重复。

思路:我们将每年的影响记录下来。第i年,P前面有多少比他菜的人Pos[i]。很显然,Pos[i]<0的话表示P会被踢出去。当第x年的第i个人能力被改为z后,有四种可能:

1.之前能力值小,后来能力值小。Pos[x]不变

2.之前能力值小,后来能力值大。Pos[x]--

3.之前能力值大,后来能力值小。Pos[x]++

4.之前能力值大,后来能力值大。Pos[x]不变。

然后维护P的位置就好了。如果某一年出现负数,则说明P会被踢出去。

由于第二年还要减掉新入的人数,所以注意第二年的时候,前一年的pos[i]-新人数。

ACCode:

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand((unsigned)time(NULL));rand();
      
#include<map>//unordered_map
#include<set>//multiset
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
 
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
      
const int MAXN=1e5+10;
//const int MAXM=10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)

struct SegTree{
	struct Tree{
		int l,r;
		int minpos;
		int lazy;
	};
	Tree T[MAXN<<2];
	
	void PushUp(int rt){
		T[rt].minpos=min(T[rt<<1].minpos,T[rt<<1|1].minpos);
	}
	void PushDown(int rt){
		if(T[rt].lazy!=0){
			T[rt<<1].lazy+=T[rt].lazy;T[rt<<1|1].lazy+=T[rt].lazy;
			T[rt<<1].minpos+=T[rt].lazy;T[rt<<1|1].minpos+=T[rt].lazy;
			T[rt].lazy=0;
		}
	}
	void Build(int l,int r,int rt,int A[]){
		T[rt].l=l;T[rt].r;
		if(l==r){
			T[rt].minpos=A[l];
			return ;
		}int mid=(l+r)>>1;
		Build(l,mid,rt<<1,A);Build(mid+1,r,rt<<1|1,A);
		PushUp(rt);
	}
	void Update(int ql,int qr,int val,int rt){
		if(ql<=T[rt].l&&T[rt].r<=qr){
			T[rt].minpos+=val;
			T[rt].lazy+=val;
			return ;
		}PushDown(rt);
		if(qr<=T[rt<<1].r) Update(ql,qr,val,rt<<1);
		else if(ql>=T[rt<<1|1].l) Update(ql,qr,val,rt<<1|1);
		else{
			Update(ql,qr,val,rt<<1);
			Update(ql,qr,val,rt<<1|1);
		}PushUp(rt);
	}
	int Query(int ql,int qr,int rt){
		if(ql<=T[rt].l&&T[rt].r<=qr) return T[rt].minpos;
		PushDown(rt);
		if(qr<=T[rt<<1].r) return Query(ql,qr,rt<<1);
		else if(ql>=T[rt<<1|1].l) return Query(ql,qr,rt<<1|1);
		else return min(Query(ql,qr,rt<<1),Query(ql,qr,rt<<1|1));
	}
};
SegTree Seg;
vector<int> G[MAXN];
int Pos[MAXN];
int A[MAXN];
int n,m,q;

int main(){
	while(~scanf("%d%d%d",&n,&m,&q)){
		for(int i=1;i<=m;++i) G[i].clear();
		int Pre=0,Nxt=0,P;
		for(int i=1;i<=n;++i) scanf("%d",&A[i]);
		P=A[1];
		for(int i=2;i<=n;++i){
			if(A[i]<P) Pre++;
			else Nxt++;
		}Pos[0]=Pre;
		for(int i=1;i<=m;++i){
			int cnt;scanf("%d",&cnt);
			Pos[i-1]-=cnt;
			Pre=0;
			for(int j=1;j<=cnt;++j){
				int x;scanf("%d",&x);G[i].push_back(x);
				if(x<P) Pre++;
			}Pos[i]+=Pos[i-1]+Pre;
		}
//		for(int i=0;i<=m;++i) printf("i=%d pos=%d\n",i,Pos[i]);
		Seg.Build(1,m,1,Pos);
		while(q--){
			int year,pos,val;scanf("%d%d%d",&year,&pos,&val);
			int old=G[year][pos-1];G[year][pos-1]=val;
//			printf("old=%d\n",old);
			if(old<P) Seg.Update(year,m,-1,1);//删一个菜鸟 
			else ;//删一个大佬 
			if(val<P) Seg.Update(year,m,1,1);//加一个菜鸟 
			else ;//加一个大佬 
			int flag=Seg.Query(1,m,1);
			if(flag<0) printf("0\n");
			else printf("1\n");
			flag=Seg.Query(year,year,1);//该点当前的位置 
		}
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值