HDU 5828 Rikka with Sequence

好久没写线段树了,这题作为一个回味..

第一种操作的话,就是一个延迟标记。

第二种操作可以暴力更新下去,但是有一个优化,如果某区间内所有值都是一样的,那么到此结束,不要继续往下面暴力更新了。

这样一来的话,pushDown的时候要注意一下,如果该区间内所有值都一样,那么延迟标记不要往下扔了,直接把该区间的信息传下去。如果该区间内所有值不一样,将延迟标记扔下去。

总体难度不算大,仔细一些就能AC。

不过这样的方法是水过去的。

10W个2 3 2 3 2 3 2 3.....

10W次操作 +6 sqrt +6 sqrt +6 sqrt.....

会变得很慢很慢。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-8;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
inline int read()
{
    char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0;
    while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar();  }
    return x;
}

const int maxn=100000+10;
struct Seg { LL sum,f,MAX,MIN; }s[4*maxn];
int T,n,m;

void pushUp(int rt)
{
    s[rt].sum=s[2*rt].sum+s[2*rt+1].sum;
    s[rt].MAX=max(s[2*rt].MAX,s[2*rt+1].MAX);
    s[rt].MIN=min(s[2*rt].MIN,s[2*rt+1].MIN);
}

void pushDown(int l,int r,int rt)
{
    if(s[rt].MIN==s[rt].MAX)
    {
        s[2*rt].MIN=s[2*rt+1].MIN=s[rt].MIN;
        s[2*rt].MAX=s[2*rt+1].MAX=s[rt].MAX;

        int fz=(l+r)/2-l+1;
        s[2*rt].sum=(LL)fz*s[rt].MIN;
        s[2*rt+1].sum=s[rt].sum-s[2*rt].sum;
        s[rt].f=s[2*rt].f=s[2*rt+1].f=0;
        return;
    }

    if(s[rt].f==0) return;

    s[2*rt].f=s[2*rt].f+s[rt].f;
    s[2*rt+1].f=s[2*rt+1].f+s[rt].f;

    s[2*rt].MAX=s[2*rt].MAX+s[rt].f;
    s[2*rt+1].MAX=s[2*rt+1].MAX+s[rt].f;

    s[2*rt].MIN=s[2*rt].MIN+s[rt].f;
    s[2*rt+1].MIN=s[2*rt+1].MIN+s[rt].f;

    int m=(l+r)/2;
    s[2*rt].sum=s[2*rt].sum+(LL)(m-l+1)*s[rt].f;
    s[2*rt+1].sum=s[2*rt+1].sum+(LL)(r-m)*s[rt].f;

    s[rt].f=0;
}

void build(int l,int r,int rt)
{
    s[rt].f=0; s[rt].MAX=0; s[rt].MIN=0; s[rt].sum=0;
    if(l==r)
    {
        scanf("%lld",&s[rt].sum);
        s[rt].f=0; s[rt].MAX=s[rt].sum; s[rt].MIN=s[rt].sum;
        return;
    }
    int m=(l+r)/2;
    build(l,m,2*rt);
    build(m+1,r,2*rt+1);
    pushUp(rt);
}

void add(int L,int R,int x,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        s[rt].f=s[rt].f+x; s[rt].MAX=s[rt].MAX+x;
        s[rt].MIN=s[rt].MIN+x; s[rt].sum=s[rt].sum+(r-l+1)*(LL)x;
        return;
    }
    pushDown(l,r,rt);
    int m=(l+r)/2;
    if(L<=m) add(L,R,x,l,m,2*rt);
    if(R>m)  add(L,R,x,m+1,r,2*rt+1);
    pushUp(rt);
}

LL quary(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return s[rt].sum;
    pushDown(l,r,rt);
    int m=(l+r)/2; LL x1=0,x2=0;
    if(L<=m) x1=quary(L,R,l,m,2*rt);
    if(R>m)  x2=quary(L,R,m+1,r,2*rt+1);
    pushUp(rt);
    return x1+x2;
}

void force(int l,int r,int rt)
{
    if(l==r)
    {
        s[rt].sum=(LL)sqrt(1.0*s[rt].sum);
        s[rt].MIN=s[rt].MAX=s[rt].sum;
        return;
    }
    if(s[rt].MIN==s[rt].MAX)
    {
        s[rt].MAX=s[rt].MIN=(LL)sqrt(1.0*s[rt].MIN);
        s[rt].sum=(LL)(r-l+1)*s[rt].MIN;
        return;
    }
    pushDown(l,r,rt);
    int m=(l+r)/2;
    if(s[2*rt].MAX!=1) force(l,m,2*rt);
    if(s[2*rt+1].MAX!=1) force(m+1,r,2*rt+1);
    pushUp(rt);
}

void update(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) { if(s[rt].MAX==1) return; force(l,r,rt); return; }
    pushDown(l,r,rt);
    int m=(l+r)/2;
    if(L<=m&&s[2*rt].MAX!=1) update(L,R,l,m,2*rt);
    if(R>m&&s[2*rt+1].MAX!=1) update(L,R,m+1,r,2*rt+1);
    pushUp(rt);
}

int main()
{
    scanf("%d",&T); while(T--)
    {
        scanf("%d%d",&n,&m); build(1,n,1);
        for(int i=1;i<=m;i++)
        {
            int op,L,R,x; scanf("%d%d%d",&op,&L,&R);
            if(op==1) { scanf("%d",&x); add(L,R,x,1,n,1); }
            else if(op==2) update(L,R,1,n,1);
            else if(op==3) printf("%lld\n",quary(L,R,1,n,1));
        }
    }
    return 0;
}
时间: 2024-10-23 14:04:38

HDU 5828 Rikka with Sequence的相关文章

判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

1 // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence 2 // 题意:三种操作,1增加值,2开根,3求和 3 // 思路:这题与HDU 4027 和HDU 5634 差不多 4 // 注意开根号的话,遇到极差等于1的,开根号以后有可能还是差1.如 5 // 2 3 2 3... 6 // 8 9 8 9... 7 // 2 3 2 3... 8 // 8 9 8 9... 9 // 剩下就是遇到区间相等的话,就直接开根号不往下传 10 11 12

HDU 5828 Rikka with Sequence(线段树 开根号)

Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2777    Accepted Submission(s): 503 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situati

HDU 5828 Rikka with Sequence (线段树+剪枝优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是求出l到r之间的和. 操作1和3就不说了,关键是开方操作. 一个一个开方,复杂度太高,无疑会T.所以我们来剪枝一下. 我们可以观察,这里一个数最多开方4,5次(loglogx次)就会到1,所以要是一段区间最大值为1的话,就不需要递归开方下去了.这是一个剪枝. 如果一段区间的数都是一样大小(最大值等于

HDU 5828 Rikka with Sequence(线段树)

题目链接:点击打开链接 思路: 对于该题, 由于存在区间加一个值, 那么所有数都可能永远不会变成1, 但是数与数之间的相对值会趋近于相等.  比如1 2 3 4 5, 进行一次根号操作变成1 1 1 2 2, 而一旦如果相等, 那么他们同时加一个数也是相等的.  所以我们增加一个标记bit[rt]表示该区间内的数是否全部相等,如果相等等于什么. 细节参见代码: #include <cstdio> #include <cstring> #include <iostream>

hdu 5204 Rikka with sequence

题意: 众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的: 如果一个无重边无自环的无向图的每个联通块都存在一条回路经过这个联通分量所有边一次且仅一次,那么就称这个无向图是优美的.请问有n个点且边数不少于m的优美的图有多少个?(在这题中,我们认为这n个点是本质不同的) 当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗? 限制: 1 <= n <= 1e5; 1 <= L <= R <= 1e18; 1 <= w <=

hdu 5204 Rikka with sequence 智商不够系列

Rikka with sequence Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5204 Description 众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:现在有一个序列,因为这个序列很任性,开始时空的.接下来发生了n个事件,每一个事件是以下两种之一:1.勇太利用黑炎龙的力量在序列的开头.结尾以及每相邻两个元素之间都插入

hdu 5204 Rikka with sequence(BestCoder Round #37)

Rikka with sequence                                                        Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 378    Accepted Submission(s): 75 Problem Description As we know, Rikk

【HDU 5828】Rikka with Sequence(线段树)

[HDU 5828]Rikka with Sequence(线段树) Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2311    Accepted Submission(s): 391 Problem Description As we know, Rikka is poor at math.

HDU 5831 Rikka with Parenthesis II(六花与括号II)

HDU 5831 Rikka with Parenthesis II (六花与括号II) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description 题目描述 As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math ta