zoukankan      html  css  js  c++  java
  • BZOJ3211 花神游历各国

    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
    ",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
  • 相关阅读:
    日期间隔之年、月、日、时、分、秒
    加减年、月、日、时、分、秒
    求总和的百分比
    返回最值所在行数据
    返回各部门工资排名前三位的员工
    生成累计和
    将字符和数字数据分离
    从字符串中删除不需要的字符
    计算字符在字符串中出现的次数
    字符串文字中包含引号
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4655282.html
Copyright © 2011-2022 走看看