[洛谷p2801]教主的魔法

题目链接:###

传送门

题目分析:###

很裸的分块题,最开始在原数组上排序WA掉了,还因此调了很久23333
(不过为什么这样一个全是bug的程序交上去会有90分啊 WOJ上甚至还能玄学A过)
大块打标记,小块暴力改,每次改了小块之后把小块所在的整个大块复制到另外一个数组里排序,询问时用二分找比C更大的第一个即可


代码:###

#include<bits/stdc++.h>
#define MAXN (1000000+5)
using namespace std;
inline int read(){
	int cnt=0,f=1;char c;
	c=getchar();
	while(!isdigit(c)){
		if(c=='-')f=-f;
		c=getchar();
	}
	while(isdigit(c)){
		cnt=cnt*10+c-'0';
		c=getchar();
	}
	return cnt*f;
}
int n,a[MAXN],q,L[MAXN],R[MAXN],add[MAXN],pos[MAXN],b[MAXN];
char opr;
int find(int l,int r,int c){
	int ll=l;int rr=r;
	int mid=(ll+rr)>>1;
	int u=pos[mid];
	if(b[rr]+add[u]<c)return -(1<<30);
//	cout<<l<<" "<<r<<" "<<c<<endl; 
	while(ll<rr){
		int mid=(ll+rr)>>1;
		if(b[mid]+add[u]>=c)rr=mid;
		else ll=mid+1;
//		cout<<ll<<" "<<mid<<" "<<rr<<endl;
	}
	
	return ll;
}
void change(int l,int r,int d){
	int p=pos[l];int q=pos[r];
	if(p==q) {
		for(register int i=l;i<=r;i++)a[i]+=d;
		for(register int i=L[p];i<=R[p];i++)b[i]=a[i];
		sort(b+L[p],b+R[p]+1);
	}
	else {
		for(register int i=l;i<=R[p];i++)a[i]+=d;
		for(register int i=L[p];i<=R[p];i++)b[i]=a[i];
		sort(b+L[p],b+R[p]+1);
		for(register int i=p+1;i<=q-1;i++)add[i]+=d;
		for(register int i=L[q];i<=r;i++)a[i]+=d;
		for(register int i=L[q];i<=R[q];i++)b[i]=a[i]; 
		sort(b+L[q],b+R[q]+1);
	}
}
int query(int l,int r,int C){
//	for(register int i=1;i<=n;i++)b[i]=a[i];
	int ans=0;
	int p=pos[l];int q=pos[r];
//	cout<<"p="<<p<<endl<<"q="<<q<<endl;
	if(p==q){ for(register int i=l;i<=r;i++)if(a[i]+add[p]>=C)ans++;}
	else {
		for(register int i=l;i<=R[p];i++) if(a[i]+add[p]>=C)ans++;
		for(register int i=p+1;i<=q-1;i++){
//			for(register int j=L[i];j<=R[i];j++)b[j]=a[j];
//			sort(b+L[i],b+R[i]+1);
			int x=find(L[i],R[i],C);
//			printf("#%d#",x);
			if(x!=-(1<<30)) ans+=(R[i]-x+1);
		}
		for(register int i=L[q];i<=r;i++){
//			printf("%d ",a[i]);
			if(a[i]+add[q]>=C)ans++;
		}
	}
	return ans;
}
int A,B,C;
int main(){
//	freopen("1.in","r",stdin);
	n=read();q=read(); 
	for(register int i=1;i<=n;i++){
		a[i]=read();b[i]=a[i];
	}
	int t=sqrt(n);
	for(register int i=1;i<=t;i++){
		L[i]=(i-1)*t+1;
		R[i]=i*t;
	}
	if(R[t]<n){
		++t;
		L[t]=R[t-1]+1;
		R[t]=n;
	}
	for(register int i=1;i<=t;i++)
		for(register int j=L[i];j<=R[i];j++)
			pos[j]=i;

	for(register int i=1;i<=t;i++)
		sort(b+L[i],b+R[i]+1);

	while(q--){
		cin>>opr;A=read();B=read();C=read();
		if(opr=='M')change(A,B,C);
		if(opr=='A')printf("%d\n",query(A,B,C));
//		for(register int i=1;i<=n;i++)printf("%d ",a[i]);
//		printf("\n");
//		for(register int i=1;i<=t;i++)printf("%d ",add[i]);
//		printf("\n");
	}
	return 0;
}

调试语句巨多,凑合看……


话说最近的博客为什么都是两句话说完的风格了啊一定是被fsy带坏了

posted @ 2019-01-22 13:20  kma_093  阅读(171)  评论(0)    收藏  举报