[洛谷P3948]数据结构 题解(差分)

[洛谷P3948]数据结构

Description

最开始的数组每个元素都是0
给出n,opt ,min,max,mod 在int范围内
A: L ,R ,X 表示把[l,R] 这个区间加上X(数组的从L到R的每个元素都加上X)
Q : L ,R 表示询问[L,R] 这个区间中元素T满足 min<=(T∗i %mod)<=max 的 T这样的数的个数(i是数组下标)(元素的值*数组下标%mod在min到max范围内)

由于 edt 请来了一位非三次元的仓鼠,他帮你用延后了部分问题,将这些询问打入了混乱时空,你的询问操作>不会超过1000次,不幸的是,对于延后的询问操作可能有很多次(小于1e7次),但是保证这些延后的询问操作之后不会再次有修改操作(就是在最后会有很多次询问,但不会进行修改)

输入格式:
给出n,opt,mod,min,max表示序列大小,操作次数,取膜,最小值,最大值

下面opt行,给出
A : L ,R ,X 表示区间加,保证X在int范围内(<2147483647)
Q :L ,R 表示区间查询满足条件的个数

再给出一个Final 值,表示后面有Final 个询问
下面Final 行,给出
L,R 表示询问区间[L,R]之间满足条件的个数

输出格式:
每行对于每个Q 操作输出Q 个数表示每次询问的值,
下面Final 行表示Final个询问的值

Solution

1.首先因为前半部分以区间修改为主,所以我们采用差分的方法使该操作变为O(1),即对于每个L,R,X,令num[L]+=X,num[R+1]-=X;

2.由于前半部分寻问非常少(小于1000次)每次都计算一遍当前数组的各个数字,O(n)处理就好;

3.对于final部分的寻问,因为没有修改,我们考虑离线处理,先进行预处理,用一个数组ok[i]记录i即其以前的元素符合条件的个数,再对于每一个询问L,R,输出ok[R]-ok[L-1]的值即可(因为ok[R]统计的是R及其以前的符合条件的元素个数,减去不在区间[L,R]内的部分,即ok[L-1]就是区间内符合要求的元素个数);

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

long long num[100100],n,m,i,j,k,minn,maxn,mod,l,r,x,t,ok[100100];
char c;

inline long long rd(){
	long long x=0;
	bool f=true;
	char c;
	c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') f=false;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return f?x:-x;
} 

inline char getc()
{
	char c=getchar();
	while(c<'A'||c>'Z')c=getchar();
	return c;
}

void modify(){
	l=rd();
	r=rd();
	x=rd();
	num[l]+=x;
	num[r+1]-=x;
}

void count(){
	l=rd();
	r=rd();
	long long ans=0;
        x=0;
	for(i=1;i<=r;++i){
		x+=num[i];
		if(i>=l&&((x*i)%mod>=minn)&&((x*i)%mod<=maxn)) ++ans;
	}
	printf("%lld\n",ans);
}

int main(){
	memset(ok,0,sizeof(ok));
	memset(num,0,sizeof(num));
	n=rd();
	t=rd();
	mod=rd();
	minn=rd();
	maxn=rd();
	for(k=1;k<=t;++k){
		c=getc();
		if(c=='A') modify();
		else count(); 
	}
	t=rd();
	x=0;
	for(i=1;i<=n;++i){
		x+=num[i];
		ok[i]=ok[i-1];
		if(((x*i)%mod>=minn)&&((x*i)%mod<=maxn))++ok[i];
	}
	for(i=1;i<=t;++i){
		l=rd();
		r=rd();
		printf("%lld\n",ok[r]-ok[l-1]);
	}
	return 0;
}

差分数组的基础参考以前的随笔:http://www.cnblogs.com/COLIN-LIGHTNING/p/8436624.html

posted @ 2018-02-28 11:00  COLINGAO  阅读(702)  评论(0编辑  收藏  举报