可以发现对于每个队伍 最小需要的防御值是max(ai-i+1)
因为打到第i个时已经加了i-1防御
然后所有队伍从小到大排序后 答案求法亦然
那么我用treap维护每个队列
用权值线段树维护答案
#include
#include
#include
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') c=nc();
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=100005;
struct node{
node *l,*r;
int size;
int val,tag,maxv;
void updata(){
maxv=val; size=1;
if (l!=NULL) maxv=max(maxv,l->maxv),size+=l->size;
if (r!=NULL) maxv=max(maxv,r->maxv),size+=r->size;
}
void mark(int t){
tag+=t,val+=t,maxv+=t;
}
void Pushdown(){
if (l!=NULL) l->mark(tag);
if (r!=NULL) r->mark(tag);
tag=0;
}
}nodes[N<<2];
int ncnt=0;
inline node* Build(int l,int r,int *a){
if (l>r) return NULL;
int mid=(l+r)>>1;
node *tmp=nodes+(++ncnt);
tmp->size=1; tmp->maxv=tmp->val=a[mid]-mid+1; tmp->tag=0;
tmp->l=Build(l,mid-1,a);
tmp->r=Build(mid+1,r,a);
tmp->updata();
return tmp;
}
typedef pair Droot;
inline int ran(){
static int x=31253125; x+=(x<<4)+1; return x&65536;
}
inline node* M(node *x,node *y){
if (!x || !y) return x?x:y;
x->Pushdown(); y->Pushdown();
if (ran()){
y->l=M(x,y->l); y->updata();
return y;
}else{
x->r=M(x->r,y); x->updata();
return x;
}
}
inline int Size(node *x){
return x?x->size:0;
}
inline Droot S(node *x,int k){
if(!x) return Droot(NULL,NULL);
x->Pushdown(); Droot y;
if(Size(x->l)>=k){
y=S(x->l,k);
x->l=y.second; x->updata();
y.second=x;
}else{
y=S(x->r,k-Size(x->l)-1);
x->r=y.first; x->updata();
y.first=x;
}
return y;
}
int n,Q;
int a[N];
int tot[N];
node *head[N];
struct SEG{
int T[N<<2],F[N<<2]; int C[N];
int n,M,TH;
inline void Build(int _n){
n=_n;
for (M=1;M>i]){
T[p<<1]+=F[p]; F[p<<1]+=F[p];
T[p<<1|1]+=F[p]; F[p<<1|1]+=F[p];
F[p]=0;
}
}
inline void Add(int s,int t,int r){
for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;){
if (~s&1) T[s^1]+=r,F[s^1]+=r;
if ( t&1) T[t^1]+=r,F[t^1]+=r;
T[s>>=1]=max(T[s<<1],T[s<<1|1]);
T[t>>=1]=max(T[t<<1],T[t<<1|1]);
}
while (s>>=1)
T[s]=max(T[s<<1],T[s<<1|1]);
}
inline int Query(){
return T[1];
}
inline void Change(int val,int num,int r){
if (r==1){
if (C[val]==0)
Add(val,val,val);
C[val]++;
Add(val+1,n,-num);
}else{
if (C[val]==1)
Add(val,val,-val);
C[val]--;
Add(val+1,n,num);
}
}
}Seg;
inline void Solve(int x,int a,int y,int b){
if (head[x]) Seg.Change(head[x]->maxv,head[x]->size,-1);
if (head[y]) Seg.Change(head[y]->maxv,head[y]->size,-1);
Droot A=S(head[x],a),B=S(head[y],b);
if (A.second) A.second->mark(Size(A.first)-Size(B.first));
if (B.second) B.second->mark(Size(B.first)-Size(A.first));
head[x]=M(B.first,A.second);
head[y]=M(A.first,B.second);
if (head[x]) Seg.Change(head[x]->maxv,head[x]->size,1);
if (head[y]) Seg.Change(head[y]->maxv,head[y]->size,1);
}
int main(){
int in; int ix,ia,iy,ib;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
Seg.Build(100000);
for (int i=1;i<=n;i++){
read(tot[i]);
for (int j=1;j<=tot[i];j++) read(a[j]);
head[i]=Build(1,tot[i],a);
if (head[i]) Seg.Change(head[i]->maxv,head[i]->size,1);
}
read(Q);
while (Q--){
read(ix); read(ia); read(iy); read(ib);
Solve(ix,ia,iy,ib);
printf("%d\n",Seg.Query());
}
return 0;
}