洛谷 P3948 数据结构(差分数组)

题目连接

    题意:
                开始每个数组的元素都是0
                给出n . opt, mod, min, max, mod在int内
                操作 A, Q
                A:L, R, X 吧 [ L, R ]    这个区间内每个元素+ X
                Q:L, R 询问 [L, R] 这个区间中元素满足 
                min <= (T * i % mod) <= max 的T这样的数的个数 
                (i是数组下标) 
                在给出一个Final值,表示有Final 个查询
                [ L, R ] 表示 询问区间 [L, R] 之间满足条件的个数 
    思路:
                数据范围:N 8e4,  opt 1e6, Final 1e7, Q <= 1e3
                时间1S
                那么A的操作就是 1e6 -1e3  = 差不多还是1e6
                操作过后直接 前缀数组  O(N) 求一下然后就是 Final操作了 
                1)如果用线段树 时间就是  O(Log(2)8e4 * 1e6 + log(2)8e4 * 1e7) 
                2)用差分数组  O(1e3 * N + 1e6 + N + Final) 

AC:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stdio.h>
using namespace std;
typedef long long ll; 
const int maxn = 1e5;
ll N, opt, Mod, Min, Max, Final;
ll F[maxn];
ll Pre[maxn];
ll Solve(int L, int R) {
	ll T = 0;
	for(int i = 1; i < L; ++i) {
		T += F[i]; 
	}
	ll Ans = 0;
	ll Tmp;
	for (int i = L; i <= R; ++i) {
		T += F[i];
		Tmp = T * i % Mod;
		if ( Tmp >= Min && Max >= Tmp) {
			Ans ++;
		}
	}
	return Ans; 
}
void bulid() {
	ll Tmp = 0;
	ll T = 0;
	int Flag = 0;
	for(int i = 1; i <= N; ++i) {
		T += F[i];
		Tmp = T * i % Mod;
		Flag = 0;
		if( Tmp >= Min && Max >= Tmp) {
			Flag = 1;
		}
		Pre[i] = Pre[i - 1] + Flag; 
	}
}
int main() {
	//freopen("in.txt", "r", stdin); 
	scanf("%lld%lld%lld%lld%lld", &N, &opt, &Mod, &Min, &Max);
	char ch[3];
	ll L, R, X;
	ll Ans = 0;
	for(int i = 1; i <= opt ; ++i) {
		scanf("%s", &ch);
		if(ch[0] == 'A') {
			scanf("%lld%lld%lld", &L, &R, &X);
			F[L] += X;
			F[R + 1] -= X;
		}
		if(ch[0] == 'Q') {
			scanf("%lld%lld", &L, &R);
			Ans = Solve(L, R);
			printf("%lld\n", Ans);
		}
	}
	scanf("%lld", &Final);
	bulid();
	for(int i = 1; i <= Final; ++i) {
		scanf("%lld%lld", &L, &R);
		printf("%lld\n", Pre[R] - Pre[L - 1]);
	} 
	return 0;
} 
发布了199 篇原创文章 · 获赞 156 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Harington/article/details/100877391