zoukankan      html  css  js  c++  java
  • UOJ #228. 基础数据结构练习题

    sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧。

    在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手。于是她的好朋友九条可怜酱给她出了一道题。

    给出一个长度为 nn 的数列 AA,接下来有 mm 次操作,操作有三种:

    1. 对于所有的 i[l,r]i∈[l,r],将 AiAi 变成 Ai+xAi+x。
    2. 对于所有的 i[l,r]i∈[l,r],将 AiAi 变成 Ai⌊Ai⌋。
    3. 对于所有的 i[l,r]i∈[l,r],询问 AiAi 的和。

    作为一个不怎么熟练的初学者,sylvia 想了好久都没做出来。而可怜酱又外出旅游去了,一时间联系不上。于是她决定向你寻求帮助:你能帮她解决这个问题吗。

    输入格式

    第一行两个数:n,mn,m。

    接下来一行 nn 个数 AiAi。

    接下来 mm 行中,第 ii 行第一个数 titi 表示操作类型:

    ti=1ti=1,则接下来三个整数 li,ri,xili,ri,xi,表示操作一。

    ti=2ti=2,则接下来三个整数 li,rili,ri,表示操作二。

    ti=3ti=3,则接下来三个整数 li,rili,ri,表示操作三。

    输出格式

    对于每个询问操作,输出一行表示答案。

    样例一

    input

    5 5
    1 2 3 4 5
    1 3 5 2
    2 1 4
    3 2 4
    2 3 5
    3 1 5
    
    

    output

    5
    6
    

    题解:
    线段树套路题,对于sqrt操作,十分的玄学,是这样做的:
    1.加法和区间求和还是老套路
    2.sqrt有如下几个讨论:
    (1).对于整个区间的数全部相等,那么直接做区间减法即可
    (2).对于区间中的最大值max,最小值min,如果min+1==max && sqrt(min)+1==sqrt(max) 也可以做区间减法
    复杂度证明请参见论文

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #define ls (node<<1)
      8 #define rs (node<<1|1)
      9 using namespace std;
     10 typedef long long ll;
     11 const int N=100005;
     12 struct node{
     13     ll max,min,mark,sum;
     14 }t[N<<2];
     15 int gi(){
     16     int str=0;char ch=getchar();
     17     while(ch>'9' || ch<'0')ch=getchar();
     18     while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
     19     return str;
     20 }
     21 int n,m,a[N];
     22 void upd(int node){
     23     t[node].max=t[ls].max>t[rs].max?t[ls].max:t[rs].max;
     24     t[node].min=t[ls].min<t[rs].min?t[ls].min:t[rs].min;
     25     t[node].sum=t[ls].sum+t[rs].sum;
     26 }
     27 void build(int l,int r,int node){
     28     if(l==r){
     29         t[node].max=t[node].min=t[node].sum=a[l];
     30         return ;
     31     }
     32     int mid=(l+r)>>1;
     33     build(l,mid,ls);build(mid+1,r,rs);
     34     upd(node);
     35 }
     36 void pushdown(int node,int l,int r){
     37     if(!t[node].mark)return ;
     38     ll k=t[node].mark;
     39     t[ls].max+=k;t[ls].min+=k;t[rs].max+=k;t[rs].min+=k;
     40     t[ls].mark+=k;t[rs].mark+=k;
     41     int mid=(l+r)>>1;
     42     t[ls].sum+=(ll)(mid-l+1)*k;t[rs].sum+=(ll)(r-mid)*k;
     43     t[node].mark=0;
     44 }
     45 void updata(int l,int r,int node,int sa,int se,int to){
     46     if(l>se || r<sa)return ;
     47     if(sa<=l && r<=se){
     48         t[node].max+=to;t[node].min+=to;t[node].mark+=to;
     49         t[node].sum+=(ll)to*(r-l+1);
     50         return ;
     51     }
     52     pushdown(node,l,r);
     53     int mid=(l+r)>>1;
     54     updata(l,mid,ls,sa,se,to);updata(mid+1,r,rs,sa,se,to);
     55     upd(node);
     56 }
     57 void sqt(int l,int r,int node,int sa,int se){
     58     if(l>se || r<sa)return ;
     59     if(sa<=l && r<=se){
     60         if(t[node].max==t[node].min){
     61             ll tmp=(ll)sqrt(t[node].max)-t[node].max;
     62             t[node].sum+=(ll)tmp*(r-l+1);t[node].min+=tmp;t[node].max+=tmp;t[node].mark+=tmp;
     63             return ;
     64         }
     65         ll q1=sqrt(t[node].max),q2=sqrt(t[node].min);
     66         if(t[node].max==t[node].min+1 && q1==q2+1){
     67             t[node].sum+=(ll)(q1-t[node].max)*(r-l+1);
     68             t[node].min+=q1-t[node].max;t[node].mark+=q1-t[node].max;
     69             t[node].max+=q1-t[node].max;
     70             return ;
     71         }
     72     }
     73     pushdown(node,l,r);
     74     int mid=(l+r)>>1;
     75     sqt(l,mid,ls,sa,se);sqt(mid+1,r,rs,sa,se);
     76     upd(node);
     77 }
     78 ll query(int l,int r,int node,int sa,int se){
     79     if(l>se || r<sa)return 0;
     80     if(sa<=l && r<=se)return t[node].sum;
     81     pushdown(node,l,r);
     82     int mid=(l+r)>>1;
     83     return query(l,mid,ls,sa,se)+query(mid+1,r,rs,sa,se);
     84 }
     85 void work()
     86 {
     87     n=gi();m=gi();
     88     for(int i=1;i<=n;i++)a[i]=gi();
     89     build(1,n,1);
     90     int flag,x,y,z;
     91     while(m--){
     92         flag=gi();x=gi();y=gi();
     93         if(flag==1){
     94             z=gi();
     95             updata(1,n,1,x,y,z);
     96         }
     97         else if(flag==2)sqt(1,n,1,x,y);
     98         else if(flag==3)printf("%lld
    ",query(1,n,1,x,y));
     99     }
    100 }
    101 
    102 int main()
    103 {
    104     freopen("pp.in","r",stdin);
    105     freopen("pp.out","w",stdout);
    106     work();
    107     return 0;
    108 }
    
    
    

  • 相关阅读:
    【英语天天读】Feed Your Mind
    【IBM Tivoli Identity Manager 学习文档】4 TIM基本概念
    【英语天天读】Dreams
    【嵌入式开发技术之串口】Linux下串口主机程序
    【IBM Tivoli Identity Manager 学习文档】3 系统部署
    【IBM Tivoli Identity Manager 学习文档】2 部署准备知识
    【Linux开发技术之常见问题】一个建立线程时常见的问题:invalid conversion from `void*' to `void*(*)(void*)
    C# winform combobox 在绑定数据之后插入一项选择项
    Response.Redirect在新窗口打开 && 3.0扩展方法
    sql字符转换函数大全
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7400182.html
Copyright © 2011-2022 走看看