# BZOJ3211 花神游历各国 【树状数组 + 并查集】

4

1 100 5 5

5

1 1 2

2 1 2

1 1 2

2 2 3

1 1 4

101

11

11

## 题解

#include<iostream>
#include<cstdio>
#include<cmath>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define lbt(x) (x & -x)
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int N,M,pre[maxn],num[maxn];
LL A[maxn];
void add(int u,LL v){while (u <= N) A[u] += v,u += lbt(u);}
LL query(int u){LL ans = 0; while(u) ans += A[u],u -= lbt(u); return ans;}
LL sum(int l,int r){return query(r) - query(l - 1);}
int find(int u){return u == pre[u] ? u : pre[u] = find(pre[u]);}
int main(){
N = RD();
REP(i,N){
pre[i] = (num[i] != 0 && num[i] != 1) ? i : i + 1;
}pre[N + 1] = N + 1;
M = RD();
int cmd,l,r,u,v;
while (M--){
cmd = RD(); l = RD(); r = RD();
if (cmd & 1) printf("%lld\n",sum(l,r));
else {
u = find(l);
while (u <= r){
v = (LL)sqrt(num[u]); add(u,v - num[u]);
num[u] = v;
if (num[u] == 1 || num[u] == 0) pre[u] = u + 1;
u++;
}
}
}
return 0;
}

posted @ 2017-12-24 10:27  Mychael  阅读(101)  评论(0编辑  收藏  举报