BZOJ 3211: 花神游历各国( 线段树 )
线段树...区间开方...明显是要处理到叶节点的
之前在CF做过道区间取模...差不多, 只有开方, 那么每个数开方次数也是有限的(0,1时就会停止), 最大的数10^9开方10+次也就不会动了.那么我们线段树多记个max就可以少掉很多不必要的操作
--------------------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define rep(i, n) for(int i = 0; i < n; i++)
#define M(l, r) (((l) + (r)) >> 1)
#define clr(x, c) memset(x, c, sizeof(x))
using namespace std;
typedef long long ll;
const int maxn = 100009;
struct Node {
Node *l, *r;
int v, mx;
ll sum;
Node():mx(0) {
l = r = NULL;
}
inline void update() {
if(l) {
mx = max(l->mx, r->mx);
sum = l->sum + r->sum;
} else
sum = mx = v;
}
} pool[maxn << 1], *pt = pool, *root;
int L, R, n, seq[maxn];
void build(Node* t, int l, int r) {
if(r > l) {
int m = M(l, r);
build(t->l = pt++, l, m);
build(t->r = pt++, m + 1, r);
} else
t->v = seq[l];
t->update();
}
void modify(Node* t, int l, int r) {
if(t->mx <= 1) return;
if(l == r)
t->v = floor(sqrt(t->v));
else {
int m = M(l, r);
if(L <= m) modify(t->l, l, m);
if(m < R) modify(t->r, m + 1, r);
}
t->update();
}
ll query(Node* t, int l, int r) {
if(L <= l && r <= R)
return t->sum;
int m = M(l, r);
return (L <= m ? query(t->l, l, m) : 0 ) + (m < R ? query(t->r, m + 1, r) : 0);
}
int main() {
// freopen("test.in", "r", stdin);
cin >> n;
for(int i = 1; i <= n; i++)
scanf("%d", seq + i);
build(root = pt++, 1, n);
int m, op;
cin >> m;
while(m--) {
scanf("%d%d%d", &op, &L, &R);
if(op == 1)
printf("%lld\n", query(root, 1, n));
else
modify(root, 1, n);
}
return 0;
}
--------------------------------------------------------------------------------------------
3211: 花神游历各国
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1414 Solved: 546
[Submit][Status][Discuss]
Description
Input
Output
每次x=1时,每行一个整数,表示这次旅行的开心度
Sample Input
4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
Sample Output
101
11
11
11
11
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9
Source