ZOJ 3813 Alternating Sum (牡丹江网络赛E题)

ZOJ 3813 Alternating Sum

题目链接

赛后补题中,这题真心恶心爆了

先推下公式,发现是隔一个位置,长度从最长每次减2,这样累加起来的和,然后就可以利用线段树维护,记录4个值,奇数和,偶数和,奇数答案和,偶数答案和,这样pushup的时候,对应要乘系数其实就是加上左边奇(偶)和乘上右边长度,线段树处理完,还有个问题就是查询可能横跨很多个区间,这样一来就要把区间进行分段,分成3段,然后和上面一样的方法合并即可,注意中间一段很长,不能一一去合并,可以推成等差数列,利用前n项和去搞

然后这题也是一直WA啊!!,一怒之下把所有可能爆longlong的地方全处理了,结果就过了- -

代码:

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

#define lson(x) ((x<<1) + 1)
#define rson(x) ((x<<1) + 2)

const long long N = 200005;
typedef long long ll;
const ll MOD = 1000000007;

long long t, n;
char str[N];

struct Node {
	long long l, r;
	ll odd, even, sum1, sum2;
	ll size() {
		return r - l + 1;
	}
} node[N * 4];

void pushup(long long x) {
	if (node[lson(x)].size() % 2) {
		node[x].odd = (node[lson(x)].odd + node[rson(x)].even) % MOD;
		node[x].even = (node[lson(x)].even + node[rson(x)].odd) % MOD;
		node[x].sum1 = ((node[lson(x)].sum1 + node[rson(x)].size() * (node[lson(x)].odd % MOD) % MOD) % MOD + node[rson(x)].sum2) % MOD;
		node[x].sum2 = ((node[lson(x)].sum2 + node[rson(x)].size() * (node[lson(x)].even % MOD) % MOD) % MOD + node[rson(x)].sum1) % MOD;
	} else {
		node[x].odd = (node[lson(x)].odd + node[rson(x)].odd) % MOD;
		node[x].even = (node[lson(x)].even + node[rson(x)].even) % MOD;
		node[x].sum1 = ((node[lson(x)].sum1 + node[rson(x)].size() * (node[lson(x)].odd % MOD) % MOD) % MOD + node[rson(x)].sum1) % MOD;
		node[x].sum2 = ((node[lson(x)].sum2 + node[rson(x)].size() * (node[lson(x)].even % MOD) % MOD) % MOD + node[rson(x)].sum2) % MOD;
	}
}

void build(long long l, long long r, long long x = 0) {
	node[x].l = l; node[x].r = r;
	if (l == r) {
		node[x].odd = str[l] - '0';
		node[x].even = 0;
		node[x].sum1 = str[l] - '0';
		node[x].sum2 = 0;
		return;
	}
	long long mid = (l + r) / 2;
	build(l, mid, lson(x));
	build(mid + 1, r, rson(x));
	pushup(x);
}

void add(long long l, long long r, long long v, long long x = 0) {
	if (node[x].l >= l && node[x].r <= r) {
		node[x].odd = v;
		node[x].even = 0;
		node[x].sum1 = v;
		node[x].sum2 = 0;
		return;
	}
	long long mid = (node[x].l + node[x].r) / 2;
	if (l <= mid) add(l, r, v, lson(x));
	if (r > mid) add(l, r, v, rson(x));
	pushup(x);
}

Node get(long long l, long long r, long long tp, long long x = 0) {
	if (node[x].l >= l && node[x].r <= r)
		return node[x];
	long long mid = (node[x].l + node[x].r) / 2;
	if (l <= mid && r > mid) {
		Node ln = get(l, r, tp, lson(x));
		Node rn;
		Node ans;
		if (ln.size() % 2) {
			rn = get(l, r, !tp, rson(x));
			ans.l = ln.l;
			ans.r = rn.r;
			ans.odd = (ln.odd + rn.even) % MOD;
			ans.even = (ln.even + rn.odd) % MOD;
			ans.sum1 = ((ln.sum1 + rn.sum2) % MOD + rn.size() * (ln.odd % MOD) % MOD) % MOD;
			ans.sum2 = ((ln.sum2 + rn.sum1) % MOD + rn.size() * (ln.even % MOD) % MOD) % MOD;
		} else {
			rn = get(l, r, tp, rson(x));
			ans.l = ln.l;
			ans.r = rn.r;
			ans.odd = (ln.odd + rn.odd) % MOD;
			ans.even = (ln.even + rn.even) % MOD;
			ans.sum1 = ((ln.sum1 + rn.sum1) % MOD + rn.size() * (ln.odd % MOD) % MOD) % MOD;
			ans.sum2 = ((ln.sum2 + rn.sum2) % MOD + rn.size() * (ln.even % MOD) % MOD) % MOD;
		}
		return ans;
	} else if (l <= mid) return get(l, r, tp, lson(x));
	else if (r > mid) return get(l, r, tp, rson(x));
}

ll query(long long l, long long r, long long tp) {
	Node tmp = get(l, r, tp);
	if (tp == 0) return tmp.sum1;
	return tmp.sum2;
}

ll sum(ll a0, ll ti, ll an, ll d) {
	if (d == 0) return a0 % MOD * ti % MOD;
	ll ci = ti + 1;
	ll b = (a0 + an);
	if (b % 2 == 0)
		b /= 2;
	else if (ci % 2 == 0)
		ci /= 2;
	return b % MOD * (ci % MOD) % MOD;
}

ll solve(ll l, ll r) {
	ll s = l % n;
	ll e = r % n;
	if (s == 0) s = n;
	if (e == 0) e = n;
	ll ti = (r - e - (l + (n - s))) / n;
	if (ti < 0)
		return query(s, e, 0) % MOD;
	long long tp = 1;
	if ((n - s + 1) % 2) tp = 0;
	if (ti == 0) {
		Node ls = get((long long)s, n, 0);
		Node rs = get(1, (long long)e, tp);
		ll ans;
		if (tp) ans = (ls.sum1 + rs.sum1) % MOD;
		else ans = (ls.sum1 + rs.sum2) % MOD;
		ans = (ans + ls.odd * e) % MOD;
		return ans;
	}
	Node ls = get((long long)s, n, 0);
	Node mids = get(1, n, tp);
	Node rs = get(1, (long long)e, tp);
	ll ans;
	if (tp) ans = ((ls.sum1 + mids.sum1 % MOD * (ti % MOD) % MOD) % MOD + rs.sum1) % MOD;
	else ans = ((ls.sum1 + mids.sum2 % MOD * (ti % MOD) % MOD) % MOD +rs.sum2) % MOD;
	ll a0 = ls.odd;
	ll d;
	if (tp) d = mids.odd;
	else d = mids.even;
	ll an = a0 + (ti - 1) * d;
	ans = (ans + sum(a0, ti - 1, an, d) % MOD * n % MOD) % MOD;
	an += d;
	ans = (ans + an % MOD * e % MOD) % MOD;
	return ans;
}

int main() {
	scanf("%lld", &t);
	while (t--) {
		scanf("%s", str + 1);
		n = strlen(str + 1);
		for (long long i = 1; i <= n; i++)
			str[i + n] = str[i];
		n *= 2;
		build(1, n);
		long long q;
		scanf("%lld", &q);
		long long v, x, d;
		ll l, r;
		while (q--) {
			scanf("%lld", &v);
			if (v == 1) {
				scanf("%lld%lld", &x, &d);
				add(x, x, d);
				add(x + n / 2, x + n / 2, d);
			} else {
				scanf("%lld%lld", &l, &r);
				printf("%lld\n", solve(l, r));
			}
		}
	}
	return 0;
}
时间: 2024-10-03 14:55:51

ZOJ 3813 Alternating Sum (牡丹江网络赛E题)的相关文章

【瞎搞】ZOJ 3818 Pretty Poem 牡丹江网络赛J题

第一种情况:ABABA. 先判断开头的A与结尾的A,得到A的长度,接着判断ABAB 中的AB与AB是否相同(ABAB的长度一定为偶数) 已经知道了A长度,AB的长度 接着判断下A 与B是否相同 第二种情况:ABABCAB-可先讲AB看成整体即DDCD 若存在一个D满足条件 可得到C的长度和位置再判断A-B是否相同A-C是否相同 B-C是否相同(暴力取A的长度咯) #include <stdio.h> #include <string.h> #include <stdlib.h

ZOJ 3817 Chinese Knot(牡丹江网络赛I题)

ZOJ 3817 Chinese Knot 题目链接 思路:万万没想到这题直接hash+暴力剪枝就可以了,把4个串正逆都hash出来,然后每次枚举起点去dfs记录下路径即可,剪枝为如果一旦有一点不匹配就不往后搜(这个很容易想到0 0) 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; typedef unsi

ZOJ 3811 zoj 3811 Untrusted Patrol牡丹江网络赛C题

去年的比赛题目,今年才搞懂AC了===|| 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cctype> 5 #include <cmath> 6 #include <algorithm> 7 #include <vector> 8 #include <queue> 9 #include <stack&g

zoj 3813 Alternating Sum(线段树)

题目链接:zoj 3813 Alternating Sum 题目大意:给定一个P,S是以P为循环的无限串,定义G(i,j),现在有两种操作: 1 x d:将P中x的位置变为d 2 l r:查询S中l-r之间所有的G(i, j)的和 解题思路:线段树的区间查询点修改. 根据G(i,j)的公式可以推导出:每次查询l~r这段区间的答案为: 奇数:sl?len+sl+2?(len?2)+sl+4?(len?4)+?+sr?1 偶数:sl?len+sl+2?(len?2)+sl+4?(len?4)+?+s

zoj 3813 Alternating Sum(2014ACMICPC Regional 牡丹江站网络赛 E)

Alternating Sum Time Limit: 2 Seconds      Memory Limit: 65536 KB There is a digit string S with infinite length. In addition, S is periodic and it can be formed by concatenating infinite repetitions of a base string P. For example, if P = 3423537, t

ZOJ 3812 We Need Medicine(牡丹江网络赛D题)

ZOJ 3812 We Need Medicine 题目链接 思路:dp[i][j][k]表示第i个物品,组成两个值为j和k的状态,这样会爆掉,所以状态需要转化一下 首先利用滚动数组,可以省去i这维,然后由于j最大记录到50,所以可以把状态表示成一个二进制数s,转化成dp[k] = s,表示组成k状态能组成s,这样空间复杂度就可以接受了,然后这题时限还可以,就这样去转移,然后记录下路径即可 代码: #include <cstdio> #include <cstring> #incl

ZOJ 3814 Sawtooth Puzzle(牡丹江网络赛F题)

ZOJ 3814 Sawtooth Puzzle 题目链接 记录状态广搜,把9个拼图都压缩成一个状态,然后去搜索,就是模拟的过程比较麻烦 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> #include <set> using namespace std; typedef unsigned long long ll; int t; int

ZOJ 2819 Average Score 牡丹江现场赛A题 水题/签到题

ZOJ 2819 Average Score Time Limit: 2 Sec  Memory Limit: 60 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5373 Description Bob is a freshman in Marjar University. He is clever and diligent. However, he is not good at math, especia

ZOJ-3811 Untrusted Patrol DFS 2014牡丹江网络赛C题

n个点,m条双向边,k个传感器.其中有l个传感器记录到了第一次到达的时间顺序,求是否有可能检查了所有的顶点. 首先判断l,l<k一定是不行的.然后按照传感器的时间顺序dfs,先从第一个传感器位置搜索dfs搜到所有的到达传感器的位置结束,如果这个传感器被标记为可访问,则从这个传感器继续搜索下一层传感器,否则是不能满足时间顺序的.最后还要判断整个图的连通性,所有的顶点都要可以到达的. #include <iostream> #include <cstdio> #include &