題目鏈接: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);//該點當前的位置
}
}
}