【线段树】 HDOJ 5152 A Strange Problem

BC的官方题解已经写的很清楚了。。。。

#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 50005
#define maxm 400005
#define eps 1e-10
//#define mod 2333333
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
//#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b, LL mod){LL res=1%mod,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

int mo[20] = {2333333,2196720,580608,165888,55296,18432,6144,2048,1024,512,256,128,64,32,16,8,4,2,1};
LL pow2[33];
vector<LL> v[maxn];
LL sum[maxn << 2];
LL add[maxn << 2];
LL a[maxn];
int n, m;

const int MOD = 2333333;

void read(void)
{
	pow2[0] = 1;
	for(int i = 1; i <= 30; i++) pow2[i] = pow2[i-1] * 2;
	for(int i = 1; i <= n; i++) scanf("%I64d", &a[i]);
}

void pushup(int o);

void build(int o, int L, int R)
{
	add[o] = 0;
	if(L == R)  {
		sum[o] = a[L];
		v[L].clear();
		v[L].push_back(a[L]);
		return;
	}
	int mid = (L + R) >> 1;
	build(lson);
	build(rson);
	pushup(o);
}

void pushup(int o)
{
	sum[o] = (sum[ls] + sum[rs]) % MOD;
}

void pushdown(int o, int L, int R)
{
	if(add[o]) {
		int mid = (L + R) >> 1;
		sum[ls] = (sum[ls] + add[o] * (mid - L + 1) % MOD) % MOD;
		sum[rs] = (sum[rs] + add[o] * (R - mid) % MOD) % MOD;
		add[ls] += add[o];
		add[rs] += add[o];
		add[o] = 0;
	}
}

LL query(int o, int L, int R, int ql, int qr)
{
	if(ql <= L && qr >= R) return sum[o];
	pushdown(o, L, R);
	int mid = (L + R) >> 1;
	LL ans = 0;
	if(ql <= mid) ans = (ans + query(lson, ql, qr)) % MOD;
	if(qr > mid) ans = (ans + query(rson, ql, qr)) % MOD;
	pushup(o);
	return ans;
}

void update(int o, int L, int R, int ql, int qr, LL x)
{
	if(ql <= L && qr >= R) {
		sum[o] = ((R - L + 1) * x % MOD + sum[o]) % MOD;
		add[o] += x;
		return;
	}
	pushdown(o, L, R);
	int mid = (L + R) >> 1;
	if(ql <= mid) update(lson, ql, qr, x);
	if(qr > mid) update(rson, ql, qr, x);
	pushup(o);
}

LL calc(vector<LL> &vec)
{
	if(vec.size() > 18) {
		LL res = 1;
		int now = 18;
		for(int i = vec.size() - 18; i < vec.size(); i++) {
			res = (powmod(2, res, mo[now]) + vec[i]) % mo[now] + mo[now];
			now--;
		}
		return res % MOD;
	}
	else {
		LL res = vec[0];
		int now = vec.size() - 1;
		int flag = 0;
		if(res >= mo[now]) {
			flag = 1;
			res = res % mo[now] + mo[now];
		}
		now--;
		for(int i = 1; i < vec.size(); i++) {
			if(flag) res = (powmod(2, res, mo[now]) + vec[i]) % mo[now] + mo[now];
			else if(res >= 30) res = (powmod(2, res, mo[now]) + vec[i]) % mo[now] + mo[now], flag = 1;
			else if(pow2[res] >= mo[now]) res = (powmod(2, res, mo[now]) + vec[i]) % mo[now] + mo[now], flag = 1;
			else {
				res = pow2[res] + vec[i];
				if(res >= mo[now]) {
					flag = 1;
					res = res % mo[now] + mo[now];
				}
			}
			now--;
		}
		return res % MOD;
	}
}

void modify(int o, int L, int R, LL x)
{
	if(L == R) {
		if(add[o]) {
			v[L][v[L].size() - 1] += add[o];
			add[o] = 0;
		}
		v[L].push_back(0);
		sum[o] = calc(v[L]);
		return;
	}
	pushdown(o, L, R);
	LL mid = (L + R) >> 1;
	if(x <= mid) modify(lson, x);
	else modify(rson, x);
	pushup(o);
}

void work(void)
{
	int ql, qr, k;
	LL x;
	build(1, 1, n);
	while(m--) {
		scanf("%d", &k);
		if(k == 1) {
			scanf("%d%d", &ql, &qr);
			printf("%I64d\n", query(1, 1, n, ql, qr));
		}
		if(k == 2) {
			scanf("%I64d", &x);
			modify(1, 1, n, x);
		}
		if(k == 3) {
			scanf("%d%d%I64d", &ql, &qr, &x);
			update(1, 1, n, ql, qr, x);
		}
	}
}

int main(void)
{
	while(scanf("%d%d", &n, &m)!=EOF) {
		read();
		work();
	}

	return 0;
}


你可能感兴趣的:(HDU)