题意是给n个数,m个询问,每次输出之前的值加上此时询问区间的值,然后区间的数字都平方。
然后发现所有的数字平方到一定次数以后如果继续平方取模就不会变化了,用这个规律可以在线段树节点维护平方次数,大于某一值时可以以后的更新可以直接忽略。
坑点是模数很大,需要把平方转化成类似快速幂的加法。
#include <bits/stdc++.h>
using namespace std;
#define maxn 111111
#define pl c<<1
#define pr (c<<1)|1
#define lson tree[c].l,tree[c].mid,c<<1
#define rson tree[c].mid+1,tree[c].r,(c<<1)|1
const unsigned long long mod = 9223372034707292160;
int n, q;
struct node {
int l, r, mid, tt;
unsigned long long sum;
bool ok;
}tree[maxn<<4];
unsigned long long a[maxn];
unsigned long long mul (unsigned long long a, unsigned long long b) { //b个a相加
if (b == 1)
return a%mod;
unsigned long long ans = 0;
ans = (mul (a, b>>1)<<1) % mod;
if (b&1)
ans += a;
return ans%mod;
}
void pushup (int c) {
if (tree[c].l == tree[c].r)
return ;
tree[c].sum = (tree[pl].sum%mod+tree[pr].sum%mod)%mod;
tree[c].ok = (tree[pl].ok&tree[pr].ok);
return ;
}
void build_tree (int l, int r, int c) {
tree[c].l = l, tree[c].r = r, tree[c].mid = (l+r)>>1, tree[c].tt = 0;
tree[c].ok = 0;
if (l == r) {
tree[c].sum = a[l];
if (tree[c].sum == 1 || tree[c].sum == 0)
tree[c].ok = 1;
return ;
}
build_tree (lson);
build_tree (rson);
pushup (c);
}
void update (int l, int r, int c) {
if (tree[c].ok)
return ;
if (l == r) {
tree[c].sum = mul (tree[c].sum, tree[c].sum) % mod;
tree[c].tt++;
if (tree[c].tt >= 30)
tree[c].ok = 1;
return ;
}
update (lson);
update (rson);
pushup (c);
}
unsigned long long query (int l, int r, int c, int x, int y) { //cout << "[[" << endl;
unsigned long long ans = 0;
if (l == x && y == r) {
ans = tree[c].sum%mod;
update (l, r, c);
}
else if (tree[c].mid >= y) {
ans = query (lson, x, y)%mod;
}
else if (tree[c].mid < x) {
ans = query (rson, x, y)%mod;
}
else {
ans = query (lson, x, tree[c].mid)%mod + query (rson, tree[c].mid+1, y)%mod;
}
ans %= mod;
pushup (c);
return ans;
}
int main () {
//freopen ("in", "r", stdin);
int t, kase = 0;
scanf ("%d", &t);
while (t--) {
scanf ("%d%d", &n, &q);
printf ("Case #%d:\n", ++kase);
for (int i = 1; i <= n; i++) {
scanf ("%lld", &a[i]);
}
build_tree (1, n, 1);
int x, y;
unsigned long long ans = 0;
while (q--) {
scanf ("%d%d", &x, &y);
ans += query (1, n, 1, x, y);
ans %= mod;
printf ("%lld\n", ans);
}
}
return 0;
}