jzoj 4146踩气球

Description
 
Input
Output
 
Sample Input
5 3
1 1 1 1 1
5 5
2 2
1 3
5
4
2
5
2
3
Sample Output
0
1
1
2
3
 
Data Constraint
 
SOl

 如果没有强制在线,我们可以整体二分。在线的话,对每个儿童的左右点打标记,这两个标记相遇了说明已经满意了。用segment tree merge 和 dsu 维护。

 

#include<bits/stdc++.h>
#define Mid (l+r>>1)
#define N 100007
#define M N*41
using namespace std;
int f[N],l[N],r[N],siz[M],lt[M],re[M],cnt,ax,L[N],R[N],tox;
int gf(int x){return f[x]^x?f[x]=gf(f[x]):x;}
void insert(int &rt,int l,int r,int pos) {
    if (!rt) rt=++cnt; siz[rt]++;
    if (l>=r) return;
    if (pos<=Mid) insert(lt[rt],l,Mid,pos); else insert(re[rt],Mid+1,r,pos);
}
int merge(int x,int y){
    if (!x||!y) return x+y;
    int ox=++cnt;
    siz[ox]=siz[x]+siz[y];
    lt[ox]=merge(lt[x],lt[y]); re[ox]=merge(re[x],re[y]);
    return ox;
}
void que(int rt,int l,int r,int L,int R) {
    if (L<=l&&r<=R) return (void) (ax+=siz[rt]);
    if (L<=Mid) que(lt[rt],l,Mid,L,R);
    if (R> Mid) que(re[rt],Mid+1,r,L,R);
}
int n,m,T,a[N],rt[N],x,last;
signed main () {
    freopen("4.in","r",stdin);
    freopen("4.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",a+i);
    for (int i=1;i<=m;i++) {
        scanf("%d%d",l+i,r+i);
        insert(rt[r[i]],1,n,l[i]); 
    }
    scanf("%d",&T);
    for (int i=1;i<=n;i++) L[i]=R[i]=f[i]=i;
    a[0]=a[n+1]=1;
    while (T--) {
        scanf("%d",&x);
        x=(x+last-1)%n+1;
        a[x]--; 
        if (!a[x]) {
            if (!a[x-1]) tox=gf(x-1),ax=0,que(rt[tox],1,n,L[tox],R[tox]),last-=ax;
//            tox=gf(x),ax=0,que(rt[tox],1,n,L[tox],R[tox]),last-=ax;
            if (!a[x+1]) tox=gf(x+1),ax=0,que(rt[tox],1,n,L[tox],R[tox]),last-=ax;
            if (!a[x-1]) {
                tox=gf(x-1);
                f[tox]=x; L[x]=L[tox]; rt[x]=merge(rt[tox],rt[x]);
            }
            if (!a[x+1]) {
                tox=gf(x+1);
                f[tox]=x; R[x]=R[tox]; rt[x]=merge(rt[tox],rt[x]);
            }
            ax=0,que(rt[x],1,n,L[x],R[x]),last+=ax;
        }
        printf("%d\n",last);
    } 
    cerr<<cnt;
    return 0;
}

 

 

转载于:https://www.cnblogs.com/rrsb/p/9878996.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值