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);//該點當前的位置 
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章