基础数据结构练习题

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

 

 

题解:  其实这个题是随便写的,举个栗子   100  20-->10 4--->3  2----> 1 1,所以我们可以猜个结论,就是在我们可以接受次的开根号这个序列趋于相同

要是这个区间的差大于1我们就暴力dfs修改,我们可以感性的知道肯定不会修改很多次,对于这个区间:  如果  maxn-minn==0,就相当于区间覆盖,

对于3 4,开根号后变成了1 2,他们的 maxn-minn还是等于1,这样子相当于一个区间加减,然后总之就是一个双标记的问题。

hint:  应该在putdown的时候更新左右孩子的信息。

#include<bits/stdc++.h>
using namespace std;
const int N=100000*5;
long long setv[N],maxv[N],minv[N],addv[N],a[N],sumv[N];
long long _max,_min,_sum;
long long n,m;
long long w;
void build(long long o,long long l,long long r)
{
    if(l==r)
    {
        sumv[o]=maxv[o]=minv[o]=a[l];
        return;
    }
    long long mid=(r+l)/2;
    build(o*2,l,mid);
    build(o*2+1,mid+1,r);
    sumv[o]=sumv[o*2+1]+sumv[o*2];
    maxv[o]=max(maxv[o*2],maxv[o*2+1]);
    minv[o]=min(minv[o*2],minv[o*2+1]);
}
void query(long long o,long long l,long long r,long long ql,long long qr,long long add)
{
    if(setv[o]>0)
    {
        _sum+=(setv[o]+add)*(long long)(min(qr,r)-max(ql,l)+1);
    }
    else if(ql<=l&&qr>=r)
    {
        _sum+=sumv[o]+(add)*(long long)(r-l+1);
    }
    else
    {
        int mid=(l+r)/2;
        if(ql<=mid) query(o*2,l,mid,ql,qr,add+addv[o]);
        if(qr>mid) query(o*2+1,mid+1,r,ql,qr,add+addv[o]);
    }
}
void maintain(int o,int l,int r)
{
    int lc=o*2,rc=o*2+1;
    if(setv[o]!=0)
    {
        sumv[o]=setv[o]*(r-l+1);
        maxv[o]=setv[o]; minv[o]=setv[o];
    }
    else
    {
        if(r>l){
        sumv[o]=sumv[rc]+sumv[lc]+addv[o]*(r-l+1);
        maxv[o]=max(maxv[rc],maxv[lc])+addv[o];
        minv[o]=min(minv[rc],minv[lc])+addv[o];}
    }
}
void Puttage(int o,int l,int r)
{
     int mid=(l+r)/2;
     int lc=o*2,rc=o*2+1;
     if(r>l){
     int lc=o*2,rc=o*2+1;
     if(setv[o]!=0)
     {
         setv[o*2]=setv[o];  setv[o*2+1]=setv[o];
         addv[rc]=addv[lc]=0;
         sumv[lc]=setv[lc]*(mid-l+1);
         maxv[lc]=setv[lc];  minv[lc]=setv[lc];
         sumv[rc]=setv[rc]*(r-mid);
         maxv[rc]=setv[rc];  minv[rc]=setv[rc];
         setv[o]=0;
     }
     else
     {
         if(setv[rc]!=0) {setv[rc]+=addv[o]; sumv[rc]=setv[rc]*(r-mid);  maxv[rc]=setv[rc];  minv[rc]=setv[rc];}
         else {addv[rc]+=addv[o]; sumv[rc]=sumv[rc]+addv[o]*(r-mid);  maxv[rc]=maxv[rc]+addv[o];  minv[rc]=minv[rc]+addv[o];}
         if(setv[lc]!=0) {setv[lc]+=addv[o]; sumv[lc]=setv[lc]*(mid-l+1);  maxv[lc]=setv[lc];  minv[lc]=setv[lc];}
         else {addv[lc]+=addv[o]; sumv[lc]=sumv[lc]+addv[lc]*(l-mid+1); maxv[lc]=maxv[lc]+addv[o]; minv[lc]=minv[lc]+addv[o];}
         addv[o]=0;
     }}
}
void change(int x,int l,int r,int ql,int qr,int k)
{
    if(ql>r||qr<l) return;
    if(ql<=l&&qr>=r)
    {
        if(l==r)
        {
            if(setv[x]==0) a[l]+=addv[x];
            else a[l]=setv[x];
            setv[x]=addv[x]=0;
            if(k==1)
            {
                a[l]+=w;
                sumv[x]=a[l];
                maxv[x]=a[l]; minv[x]=a[l];
                return;
            }
            else
            {
                a[l]=(int)sqrt(a[l]);
                sumv[x]=a[l];
                maxv[x]=a[l]; minv[x]=a[l];
                return;
            }
        }
        if(k==1)
        {
            if(setv[x]>0)
            {
                setv[x]+=w;
                maintain(x,l,r);
                return;
            }
            else
            {
                addv[x]+=w;
                maintain(x,l,r);
                return;
            }
        }
        else
        {
            _max=maxv[x];  _min=minv[x];
            if(_max==_min)
            {
                int temp=(int)sqrt(_min);
                setv[x]=temp;
                if(addv[x]!=0) addv[x]=0;
                maintain(x,l,r);
                return;
            }
            else
            {
                if(_max-_min==1)
                {
                    int temp=(int)sqrt(_max);
                    int temp2=(int)sqrt(_min);
                    if(temp-temp2==1)
                    {
                        addv[x]-=_max-temp;
                        maintain(x,l,r);
                        return;
                    }
                    else if(temp-temp2==0)
                    {
                        setv[x]=temp;
                        if(addv[x]!=0) addv[x]=0;
                        maintain(x,l,r);
                        return;
                    }
                    else
                    {
                        Puttage(x,l,r);
                        int mid=(r+l)/2;
                        maintain(x*2,l,mid);
                        maintain(x*2+1,mid+1,r);
                    }
                }
                else
                {
                    Puttage(x,l,r);
                    int mid=(r+l)/2;
                    maintain(x*2,l,mid);
                    maintain(x*2+1,mid+1,r);
                }
            }
        }
    }
    else
    {
        Puttage(x,l,r);
        int mid=(r+l)/2;
        maintain(x*2,l,mid);
        maintain(x*2+1,mid+1,r);
    }
    int mid=(r+l)/2;
    change(x*2,l,mid,ql,qr,k);
    change(x*2+1,mid+1,r,ql,qr,k);
    maintain(x,l,r);
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int t;
        int ql,qr;
        scanf("%d",&t);
        if(t==1)
        {
            scanf("%d%d%lld",&ql,&qr,&w);
            change(1,1,n,ql,qr,1);
        }
        else if(t==2)
        {
            scanf("%d%d",&ql,&qr);
            change(1,1,n,ql,qr,2);
        }
        else
        {
            _sum=0;
            scanf("%d%d",&ql,&qr);
            query(1,1,n,ql,qr,0);
            printf("%lld\n",_sum);
        }
    }
  //  return 0;
}
//3802450110

  

posted @ 2017-07-22 12:01  Heilce  阅读(522)  评论(0编辑  收藏  举报