• bzoj4631 踩气球 (树状数组+线段树)


    4631: 踩气球

    Time Limit: 10 Sec Memory Limit: 256 MB
    Submit: 423 Solved: 217
    [Submit][Status][Discuss]
    ## Description 六一儿童节到了, SHUXK 被迫陪着M个熊孩子玩一个无聊的游戏:有N个盒子从左到右排成一排,第i个盒子里装着Ai个气球。 SHUXK 要进行Q次操作,每次从某一个盒子里拿出一个没被踩爆的气球,然后熊孩子们就会立刻把它踩爆。 这M个熊孩子每个人都指定了一个盒子区间[Li, Ri]。 如果某一个时刻,一个熊孩子发现自己选定的盒子区间[Li, Ri]中的所有气球都已经被踩爆了,他就会非常高兴(显然之后他一直会很高兴)。 为了不辜负将自己的任务强行塞给 SHUXK 的那个人的期望, SHUXK 想向你询问:他每次操作过后会有多少个熊孩子很高兴。 ## Input 第一行包含两个正整数N和M,分别表示盒子和熊孩子的个数。 第二行包含N个正整数Ai( 1 < = Ai < = 10^5),表示每个盒子里气球的数量。 以下M行每行包含两个正整数Li, Ri( 1 < = Li < = Ri < = N),分别表示每一个熊孩子指定的区间。 以下一行包含一个正整数Q,表示 SHUXK 操作的次数。 以下Q行每行包含一个正整数X,表示这次操作是从第X个盒子里拿气球。为了体现在线,我们对输入的X进行了加密。 假设输入的正整数是x',那么真正的X = (x' + Lastans − 1)Mod N + 1。其中Lastans为上一次询问的答案。对于第一个询问, Lastans = 0。 输入数据保证1 < = x' < = 10^9, 且第X个盒子中有尚未被踩爆的气球。 N < = 10^5 ,M < = 10^5 ,Q < = 10^5 ## Output 包含Q行,每行输出一个整数,表示 SHUXK 一次操作后询问的答案。答案的顺序应与输入数据的顺序保持一致。

    (L[i])为一段全(0)区间的左端点,(R[i])为右端点;
    把一个点(i)变成(0),相当于把它左右两段全(0)的区间连起来;
    此时所有 (L[i-1]<=l<=i)(i<=r<=R[i+1]) 的区间都会变得愉悦;
    然后就变成了二维数点,树状数组+线段树,边界特判一下就行了;
    AC GET☆DAZE

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define N 100039
    #define mod 20070831
    #define inf 0x3f3f3f3f 
    #define ll long long
    using namespace std;
    struct Seg_Tree
    {
    	int ls,rs,w;
    }tree[N*2*39];
    int n,m,q,num[N],L[N],R[N],tot,root[N],ans;
    int make_new(int &k)
    {
    	return !k ? k=++tot : k;
    }
    void update(int k,int l,int r,int v)
    {
    	tree[k].w++;
    	if(l==r) return;
    	int mid=l+r>>1;
    	if(v<=mid) update(make_new(tree[k].ls),l,mid,v);
    	else update(make_new(tree[k].rs),mid+1,r,v);
    }
    int query(int k,int l,int r,int lv,int rv)
    {
    	if(!k || (lv<=l && r<=rv)) return tree[k].w;
    	int mid=l+r>>1;
    	if(rv<=mid) return query(tree[k].ls,l,mid,lv,rv);
    	else if(mid<lv) return query(tree[k].rs,mid+1,r,lv,rv);
    	else return query(tree[k].ls,l,mid,lv,mid)+query(tree[k].rs,mid+1,r,mid+1,rv);
    }
    void update_bit(int p,int v)
    {
    	while(p<=n)
    	{
    		update(make_new(root[p]),1,n,v);
    		p+=(-p&p);
    	}
    }
    int query_bit(int p,int l,int r)
    {
    	int res=0;
    	while(p)
    	{
    		res+=query(root[p],1,n,l,r);
    		p-=(-p&p);
    	}
    	return res;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int a=1;a<=n;a++)
    	{
    		scanf("%d",&num[a]);
    		L[a]=R[a]=a;
    	}
    	for(int a=1,b,c;a<=m;a++)
    	{
    		scanf("%d%d",&b,&c);
    		update_bit(b,c);
    	}
    	scanf("%d",&q);
    	for(int a=1,b,c,d;a<=q;a++)
    	{
    		scanf("%d",&b);
    		((b+=ans-1)%=n)++;
    		num[b]--;
    		if(!num[b])
    		{
    			c=((b>1 && !num[b-1]) ? L[b-1] : b);
    			d=((b<n && !num[b+1]) ? R[b+1] : b);
    			ans+=query_bit(b,b,d)-query_bit(c-1,b,d);
    			if(b>1 && !num[b-1] && b<n && !num[b+1])
    			{
    				L[R[b+1]]=L[b-1],R[L[b-1]]=R[b+1];
    			}
    			else if(b>1 && !num[b-1]) L[b]=L[b-1],R[L[b-1]]=b;
    			else if(b<n && !num[b+1]) L[R[b+1]]=b,R[b]=R[b+1];
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    加入创业公司有什么利弊
    Find Minimum in Rotated Sorted Array II
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Find Minimum in Rotated Sorted Array
    Remove Duplicates from Sorted Array
    Spiral Matrix
    Spiral Matrix II
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/Sinogi/p/8942006.html
Copyright © 2020-2023  润新知