码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ3211 花神游历各国

时间:2015-07-17 20:26:18      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:

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

Sample Output

101

11

11

HINT

 

对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9

 

每个数最多log(logAi)次就会变成0或1,所以每次暴力修改一个单点可行。
但我们怎么找到区间中所有不是0和1的点呢?用并查集维护每个位置下一个合法的位置,细节见代码。
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
typedef long long ll;
inline ll read() {
    ll x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==-) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-0;
    return x*f;
}
const int maxn=100010;
int n,fa[maxn],A[maxn];
inline int findset(int x) {return !fa[x]||x==fa[x]?x:fa[x]=findset(fa[x]);}
ll c[maxn];
void add(int x,ll v) {for(;x<=n;x+=x&-x) c[x]+=v;}
ll sum(int x) {ll ret=0;for(;x;x-=x&-x) ret+=c[x];return ret;}
int main() {
    n=read();
    rep(1,n) {
        add(i,A[i]=read());
        if(A[i]<=1) fa[i]=i+1;
    }
    int q=read();
    while(q--) {
        int t=read(),l=read(),r=read();
        if(t==1) printf("%lld\n",sum(r)-sum(l-1));
        else {
            for(int i=findset(l);i<=r;i=findset(i+1)) {
                int t=sqrt(A[i]);
                add(i,t-A[i]);A[i]=t;
                if(A[i]<=1) fa[i]=findset(i+1);
            }
        }
    }
    return 0;
}
View Code

 

BZOJ3211 花神游历各国

标签:

原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/4655282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!