DarkBZOJ传送门


解析:

这还是一个区间问题。

思路:

一看是一个区间问题,似乎要用线段树,但是由于每次询问的CC在变化,所以线段树无法维护足够的信息来回答询问。

说线段树对询问分块维护的你是魔鬼吗?

这里带来一种好想好写的做法,分块,小部分暴力,整块块内排序+二分查找

我们维护一个bb数组,是分块排序后的aa数组,对于每个块维护加法标记,整块询问的时候直接二分查找(lowerboundlowerbound调不出来不如直接手写二分)。。。

注意当每个块有部分修改的时候,我们直接对这一个块整块重新排序。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num; 
}

inline void outint(int a){
	static char ch[23];
	if(a==0)pc('0');
	while(a)ch[++ch[0]]=a-a/10*10,a/=10;
	while(ch[0])pc(ch[ch[0]--]^48);
}

inline char getalpha(){
	re char c;
	while(!isalpha(c=gc()));
	return c;
}

cs int N=1000006;
int block[N];
int B;
int a[N];
int b[N];
int add[1003];
int n,q;

inline void sort(int x){
	int l=(x-1)*B+1,r=min(x*B,n);
	for(int re i=l;i<=r;++i)b[i]=a[i];
	sort(b+l,b+r+1);
}

inline int find(int x,int v){
	int l=(x-1)*B+1,r=min(x*B,n);
    int last=r;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(b[mid]<v)l=mid+1;
        else r=mid-1;
    }
    return last-l+1;
}

inline int query(int l,int r,int v){
	int ans=0;
	if(block[l]==block[r]){
		for(int re i=l;i<=r;++i)
		if(a[i]+add[block[i]]>=v)++ans;
		return ans;
	}
	for(int re i=l;block[i]==block[l];++i)if(a[i]+add[block[i]]>=v)++ans;
	for(int re i=r;block[i]==block[r];--i)if(a[i]+add[block[i]]>=v)++ans;
	for(int re i=block[l]+1;i<block[r];++i)ans+=find(i,v-add[i]);
	return ans;
}

inline void update(int l,int r,int v){
	if(block[l]==block[r]){
		for(int re i=l;i<=r;++i)a[i]+=v;
		sort(block[l]);
		return ;
	}
	for(int re i=l;block[i]==block[l];++i)a[i]+=v;sort(block[l]);
	for(int re i=r;block[i]==block[r];--i)a[i]+=v;sort(block[r]);
	for(int re i=block[l]+1;i<block[r];++i)add[i]+=v;
}

signed main(){
	n=getint();q=getint();
	B=sqrt(n);
	for(int re i=1;i<=n;++i){
		a[i]=getint();
		block[i]=(i-1)/B+1;
	}
	for(int re i=1;i<=n/B+(n%B!=0);++i)sort(i);
	while(q--){
		char op=getalpha();int l=getint(),r=getint(),v=getint();
		(op=='M')?(update(l,r,v)):(outint(query(l,r,v)),(void)pc('\n'));
	}
	return 0;
} 
posted on 2018-10-14 16:14  zxyoi_dreamer  阅读(96)  评论(0编辑  收藏