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\n",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 }

 


posted @ 2017-08-20 15:25  PIPIBoss  阅读(443)  评论(0)    收藏  举报