2016多校训练Contest8: 1008 Rikka with Sequence hdu5828

Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has an array A with n numbers. Then he makes m operations on it. 

There are three type of operations:

1 l r x : For each i in [l,r], change A[i] to A[i]+x
2 l r : For each i in [l,r], change A[i] to  A[i]
3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]

It is too difficult for Rikka. Can you help her?
 

Input
The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.

For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.

It is guaranteed that 1<=A[i],x<=100000.
 

Output
For each operation of type 3, print a lines contains one number -- the answer of the query.
 

Sample Input
  
  
1 5 5 1 2 3 4 5 1 3 5 2 2 1 4 3 2 4 2 3 5 3 1 5
 

Sample Output
  
  
5 6


考试的时候写了个近似暴力的东西。。

线段树维护一个Tag表示区间是否相同,相同就直接做sqrt否则往下查找。那时候过了

后来hdu加数据把这个做法卡掉了

其实这个时候只要维护一下区间最小值和最小值+1的个数就可以

3 4,开根再+2这样如果不维护的话就会无限循环

而如果存在最小值和最小值+2,多次开根操作后他们的差会变成1,因而维护min和min+1即可保证复杂度

附考试时候代码。加了补丁的版本没有调出来...

***一开始公布的STD也似乎T掉了***

#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree
{
    int l,r;
    long long s;
    long long tag1,tag2;
}tr[800001];
long long a[100001];
inline void up(int p)
{
    tr[p].s=tr[p*2].s+tr[p*2+1].s;
    if(tr[p*2].tag2==tr[p*2+1].tag2)
        tr[p].tag2=tr[p*2].tag2;
    else
        tr[p].tag2=0;
}
inline void push(int p)
{
    if(tr[p].tag2!=0)
    {
        long long l=tr[p].r-tr[p].l+1;
        tr[p*2].s=tr[p].tag2*(l-l/2);
        tr[p*2+1].s=tr[p].tag2*(l/2);
        tr[p*2].tag1=0;
        tr[p*2+1].tag1=0;
        tr[p*2].tag2=tr[p].tag2;
        tr[p*2+1].tag2=tr[p].tag2;
        tr[p].tag1=0;
        return ;
    }
    long long l=tr[p].r-tr[p].l+1;
    tr[p*2].s+=tr[p].tag1*(l-l/2);
    tr[p*2+1].s+=tr[p].tag1*(l/2);
    tr[p*2].tag1+=tr[p].tag1;
    tr[p*2+1].tag1+=tr[p].tag1;
    if(tr[p*2].tag2!=0)
        tr[p*2].tag2+=tr[p].tag1;
    if(tr[p*2+1].tag2!=0)
        tr[p*2+1].tag2+=tr[p].tag1;
    tr[p].tag1=0;
}
inline void build(int p,int l,int r)
{
    tr[p].l=l;
    tr[p].r=r;
    if(l!=r)
    {
        int mid=(l+r)/2;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        up(p);
    }
    else
    {
        tr[p].s=a[l];
        tr[p].tag2=a[l];
    }
}
inline void inc(int p,int l,int r,long long x)
{
    if(l<=tr[p].l&&tr[p].r<=r)
    {
        if(tr[p].tag2!=0)
        {
            tr[p].tag2+=x;
            tr[p].s=(long long)(tr[p].r-tr[p].l+1)*tr[p].tag2;
            tr[p].tag1=0;
        }
        else
        {
            tr[p].s+=(long long)(tr[p].r-tr[p].l+1)*x;
            tr[p].tag1+=x;
        }
    }
    else
    {
        push(p);
        int mid=(tr[p].l+tr[p].r)/2;
        if(l<=mid)
            inc(p*2,l,r,x);
        if(r>mid)
            inc(p*2+1,l,r,x);
        up(p);
    }
}
inline void sq(int p,int l,int r)
{
    if(l<=tr[p].l&&tr[p].r<=r&&tr[p].tag2!=0)
    {
        tr[p].tag2=sqrt(tr[p].tag2);
        tr[p].s=(long long)(tr[p].r-tr[p].l+1)*tr[p].tag2;
        tr[p].tag1=0;
        push(p);
    }
    else
    {
        push(p);
        int mid=(tr[p].l+tr[p].r)/2;
        if(l<=mid)
            sq(p*2,l,r);
        if(r>mid)
            sq(p*2+1,l,r);
        up(p);
    }
}
inline long long ask(int p,int l,int r)
{
    if(l<=tr[p].l&&tr[p].r<=r)
        return tr[p].s;
    else
    {
        push(p);
        int mid=(tr[p].l+tr[p].r)/2;
        long long ans=0;
        if(l<=mid)
            ans+=ask(p*2,l,r);
        if(r>mid)
            ans+=ask(p*2+1,l,r);
        up(p);
        return ans;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T>0)
    {
        T--;
        int n,m;
        scanf("%d%d",&n,&m);
        int i;
        for(i=1;i<=n;i++)
            scanf("%I64d",&a[i]);
        memset(tr,0,sizeof(tr));
        build(1,1,n);
        int x,l,r;
        for(i=1;i<=m;i++)
        {
            scanf("%d",&x);
            if(x==1)
            {
                scanf("%d%d%d",&l,&r,&x);
                inc(1,l,r,x);
            }
            else if(x==2)
            {
                scanf("%d%d",&l,&r);
                sq(1,l,r);
            }
            else
            {
                scanf("%d%d",&l,&r);
                printf("%I64d\n",ask(1,l,r));
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值