• HDU5828 Rikka with Sequence 线段树


    分析:这个题和bc round 73应该是差不多的题,当时是zimpha巨出的,那个是取phi,这个是开根

    吐槽:赛场上写的时候直接维护数值相同的区间,然后1A,结果赛后糖教一组数据给hack了,仰慕

            由于是开根,所以存在两个数刚开始差为1,加上某数再开根依旧是差1,这样维护相同数区间的就没用了

            比如(2,3) +6-->(8,9)开根-->(2,3)如果全是这样的操作,即使维护相同的数,每次开根的复杂度都是O(N),不T才怪

            这样只需要维护区间最大值最小值,当差1的时候,看看是否开根后还是差1,这样就可以变开根为减了

            加强数据后,1591ms。。。(还是太年轻)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <stdlib.h>
    using namespace std;
    typedef long long LL;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int 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 N=1e5+1;
    LL sum[N<<2],lz[N<<2],mx[N<<2],mn[N<<2];
    void up(int rt){
      sum[rt]=sum[rt<<1]+sum[rt<<1|1];
      mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
      mn[rt]=min(mn[rt<<1],mn[rt<<1|1]);
    }
    void build(int rt,int l,int r){
      lz[rt]=0;
      if(l==r){sum[rt]=read();mn[rt]=mx[rt]=sum[rt];return;}
      int mid=l+r>>1;
      build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
      up(rt);
    }
    void down(int rt,int l,int r){
      if(lz[rt]!=0){
        int mid=l+r>>1; 
        lz[rt<<1]+=lz[rt];
        lz[rt<<1|1]+=lz[rt];
        mn[rt<<1]+=lz[rt];
        mx[rt<<1]+=lz[rt];
        mx[rt<<1|1]+=lz[rt];
        mn[rt<<1|1]+=lz[rt];
        sum[rt<<1]+=lz[rt]*(mid-l+1);
        sum[rt<<1|1]+=lz[rt]*(r-mid);
        lz[rt]=0; 
      } 
    }
    int x,y,t,T,n,m;
    void kaigen(int rt,int l,int r){
      if(x<=l&&r<=y){
         if(mx[rt]==mn[rt]){
            lz[rt]-=mx[rt];
            mx[rt]=sqrt(mx[rt]);
            mn[rt]=mx[rt];
            lz[rt]+=mx[rt];
            sum[rt]=mx[rt]*(r-l+1);
            return;
         }
         else if(mx[rt]==mn[rt]+1){
           LL x1=sqrt(mx[rt]);
           LL x2=sqrt(mn[rt]);
           if(x1==x2+1){
              lz[rt]-=(mx[rt]-x1);
              sum[rt]-=(mx[rt]-x1)*(r-l+1);
              mx[rt]=x1;mn[rt]=x2;
              return;
           } 
        } 
      }
      int mid=l+r>>1;down(rt,l,r);
      if(x<=mid)kaigen(rt<<1,l,mid);
      if(y>mid)kaigen(rt<<1|1,mid+1,r);
      up(rt);
    }
    void add(int rt,int l,int r){
      if(x<=l&&r<=y){
        lz[rt]+=t;
        sum[rt]+=1ll*(r-l+1)*t;
        mx[rt]+=t;mn[rt]+=t;
        return ;
      }
      int mid=l+r>>1;down(rt,l,r);
      if(x<=mid)add(rt<<1,l,mid);
      if(y>mid)add(rt<<1|1,mid+1,r);
      up(rt);
    }
    LL get(int rt,int l,int r){
      if(x<=l&&r<=y)return sum[rt];
      int mid=l+r>>1;down(rt,l,r);
      LL ret=0;
      if(x<=mid)ret+=get(rt<<1,l,mid);
      if(y>mid)ret+=get(rt<<1|1,mid+1,r);
      return ret;
    }
    int main(){
      T=read();
      while(T--){
        n=read();m=read();
        build(1,1,n);
        while(m--){
          int op;
          op=read();x=read();y=read();
          if(op==1){
            t=read();add(1,1,n);
          }
          else if(op==2)kaigen(1,1,n);
          else printf("%I64d
    ",get(1,1,n));
        }
      }
      return 0;
    }
    View Code
  • 相关阅读:
    js getAttribute()和setAttribute()方法
    FCKeditor上传图片显示叉叉的问题的解决方案
    数据导出
    插入多种格式的网页播放器
    注册机...郁闷..
    AJAX效果
    2003下使用JMAIL问题解决办法
    ASP无组件上传带进度条
    MSSQL查询题解
    在线转flv+flash在线录制视频
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5765045.html
Copyright © 2020-2023  润新知