• 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

     

    c++的除法是向下取整,很明显,(a+b)/k!=a/k+b/k(在向下取整的情况下),而根号,很明显根号(a)+根号(b)!=根号(a+b)

    第一个想法就是暴力,对于每个要改动的区间l~r,把里面的每个点都单独除,但这样就会把时间复杂度卡得比大暴力都慢(因为多个常数),所以怎么优化?

    我们对于每个区间,维护她的最大值和最小值,然后每次修改时,如果这个区间的最大值根号和最小值的根号一样,说明这个区间整体根号不会产生误差,就直接修改(除法同理)

    其中,lazytage把除法当成减法,记录的是这个区间里每个元素减去的值。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define MAXN 1000010
    #define REP(i,k,n) for(int i=k;i<=n;i++)
    #define in(a) a=read()
    using namespace std;
    int read(){
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar())
            if(ch=='-')
              f=-1;
        for(;isdigit(ch);ch=getchar())
            x=x*10+ch-'0';
        return x*f;
    }
    struct node{
        int l,r;
        long long lz,sum,maxx,minn;
    }tree[MAXN<<2];
    int n,m,input[MAXN];
    inline void build(int i,int l,int r){
        tree[i].l=l;tree[i].r=r;
        if(l==r){
            tree[i].sum=tree[i].minn=tree[i].maxx=input[l];
            return ;
        }
        int mid=(l+r)>>1;
        build(i*2,l,mid);
        build(i*2+1,mid+1,r);
        tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
        tree[i].minn=min(tree[i*2].minn,tree[i*2+1].minn);
        tree[i].maxx=max(tree[i*2].maxx,tree[i*2+1].maxx);
        return ;
    }
    inline void push_down(int i){
        if(!tree[i].lz)  return ;
        long long k=tree[i].lz;
        tree[i*2].lz+=k;
        tree[i*2+1].lz+=k;
        tree[i*2].sum-=(tree[i*2].r-tree[i*2].l+1)*k;
        tree[i*2+1].sum-=(tree[i*2+1].r-tree[i*2+1].l+1)*k;
        tree[i*2].minn-=k;
        tree[i*2+1].minn-=k;
        tree[i*2].maxx-=k;
        tree[i*2+1].maxx-=k;
        tree[i].lz=0;
        return ;
    }
    inline void Sqrt(int i,int l,int r){
        if(tree[i].l>=l && tree[i].r<=r && (tree[i].minn-(long long)sqrt(tree[i].minn))==(tree[i].maxx-(long long)sqrt(tree[i].maxx))){
            long long u=tree[i].minn-(long long)sqrt(tree[i].minn);
            tree[i].lz+=u;
            tree[i].sum-=(tree[i].r-tree[i].l+1)*u;
            tree[i].minn-=u;
            tree[i].maxx-=u;
                //cout<<"i"<<i<<" "<<tree[i].sum<<endl;
            return ;
        }
        if(tree[i].r<l || tree[i].l>r)  return ;
        push_down(i);
        if(tree[i*2].r>=l)  Sqrt(i*2,l,r);
        if(tree[i*2+1].l<=r)  Sqrt(i*2+1,l,r);
        tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
        tree[i].minn=min(tree[i*2].minn,tree[i*2+1].minn);
        tree[i].maxx=max(tree[i*2].maxx,tree[i*2+1].maxx);
        //cout<<"i"<<i<<" "<<tree[i].sum<<endl;
        return ;
    }
    inline long long search(int i,int l,int r){
        if(tree[i].l>=l && tree[i].r<=r)
            return tree[i].sum;
        if(tree[i].r<l || tree[i].l>r)  return 0;
        push_down(i);
        long long s=0;
        if(tree[i*2].r>=l)  s+=search(i*2,l,r);
        if(tree[i*2+1].l<=r)  s+=search(i*2+1,l,r);
        return s;
    }
    int main(){
        in(n);
        REP(i,1,n)  in(input[i]);
        build(1,1,n);
        in(m);
        int a,b,c;
        REP(i,1,m){
            in(a);in(b);in(c);
            if(a==1)
                printf("%lld
    ",search(1,b,c));
            if(a==2){
                Sqrt(1,b,c);
                //for(int i=1;i<=7;i++)
                //    cout<<tree[i].sum<<" ";
               // cout<<endl;
            }
        }
    }
  • 相关阅读:
    微服务-SpringCloud学习系列(二):注册中心Eureka
    Spring Security系列(一)简介
    程序人生(一)--习惯与性格
    JavaEE系列(一)--Filter技术
    JavaEE系列(一)--Servlet技术
    微服务-SpringCloud学习系列(一):认识微服务
    mongoDB安装
    php遍历目录下的文件
    mysql创建视图
    ssh 安全策略
  • 原文地址:https://www.cnblogs.com/jason2003/p/9708825.html
Copyright © 2020-2023  润新知