『HDU 5828』Rikka with Sequence 【加强版已过】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828
转载链接:http://blog.csdn.net/xtttgo/article/details/52184771

数据加强后代码AC
题意:
线段树基本操作题
给你一个区间 有3个指令
1 l r x:【l,r】+x;
2 l r:【l,r】中的每个元素都得开根号
3 l r : 【l,r】中的值的和

个人感想:
马丹,我今天做了一个上午,才告诉我数据加强了,大部分题解都是T的,然后我也不会了…我只能说说我的想法吧,我现在也没找到一个blog能过的…我这种蒟蒻看不懂大牛的题解…

这题如果有做过区间开根的朋友应该第一想法就是 对于根号的单点更新,直到整段区间1或者相同的时候合并成单点,然后相当于对区间操作时转化成单点操作.

就算会做,但现在也卡不过了,数据加强了…当时比赛的时候,我也有这个想法,我是感觉会T我都不敢写,然后大部分题解都说合并就可以过了…数据加强后,真的一个都过不了了… 标程也不能过,简直什么鬼…

附加:

现在22:14分,马丹我今天敲了一天了这道题,我终于AC掉了,参考了一下大牛的文章,然后再在自己的基础上改的,转载的大牛文章说有这样的数据 2 3 2 3 2 3…,然后不断的+d,然后再开根,无限的这样子就会必然会T.
然后看了一下大牛文章,当时大牛没修改它原本文章的表达,反正有点奇怪,之后我悟道了什么意思.
这挺神奇的思想,我是没考虑过…
假设某一段区间的最大值x,和最小值y.
如果极差>1,那么这个极差经过很少的次数开根号, 其中的极差也会变得越来越小,
用公式来表达 假设当前这段区间要**+d**,然后再开根号.
必然有这样的式子

##\( \lfloor \sqrt{x+d} \rfloor - \lfloor \sqrt{y+d} \rfloor <= \lfloor \sqrt{x} \rfloor - \lfloor \sqrt{y} \rfloor \)##

就是他的极差会越来越小,反正开一次根号都变得越来越小.
所以我们很容易就求到这个段区间的值.
这里有个小极巧
所以 极差<=1的时候可以特殊处理
假设 这段区间极差==1,那么我们很容易求到这段区间的最大最小值,
因为我们知道上一次的 Sum
所以我们可以这样, 最大值的个数=Sum-(r-l+1)最小值.然后就顺便求出最大值,然后*如果当前区间要开根号的话,**直接就可以求出来了…

好累…回宿舍…

T代码:

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const ll INF = 0x3f3f3f3f;
const ll maxn = 1e5 + 10;


ll Scan()//读入整数外挂.
{
    ll res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
void Out(ll a)    //输出外挂
{
    if(a > 9)
        Out(a / 10);
    putchar(a % 10 + '0');
    //prllf("\n");
}
/*1.加上一个值
  2.开根号
  3.计算总值
*/
int T;
int n, m;
int op;
int l, r;
ll x;
ll A[maxn];

class Node
{
public:
    int l;
    int r;
    ll sum;
    ll lazy;
    ll flag;//用flag来判断是否有整段的值都是一样的.
};

Node node[4 * maxn];

void pushup(int k)
{
    if(node[lson].flag==node[rson].flag&&node[lson].flag)
    {
       node[k].flag=node[lson].flag;
    }
    else node[k].flag=0;

    node[k].sum=node[lson].sum+node[rson].sum;
}

void pushdown(int k)
{

    if(node[k].flag)
    {
        node[lson].flag=node[k].flag;
        node[rson].flag=node[k].flag;

        node[lson].sum=(node[lson].r-node[lson].l+1)*node[k].flag;
        node[rson].sum=(node[rson].r-node[rson].l+1)*node[k].flag;

        node[k].lazy=0;
    }
    if(node[k].lazy)
    {
        node[lson].sum+=(node[lson].r-node[lson].l+1)*node[k].lazy;
        node[rson].sum+=(node[rson].r-node[rson].l+1)*node[k].lazy;

        if(node[lson].flag)node[lson].flag+=node[k].lazy;
        if(node[rson].flag)node[rson].flag+=node[k].lazy;

       node[lson].lazy+=node[k].lazy;
       node[rson].lazy+=node[k].lazy;

       node[k].lazy=0;
    }

    return;
}
void Build(int l,int r,int k)
{
    node[k].l=l;
    node[k].r=r;
    node[k].lazy=0;
    node[k].flag=0;
    if(l==r)
    {
       node[k].flag=node[k].sum=A[l];
       return ;
    }

    int mid=(l+r)/2;

    Build(l,mid,lson);
    Build(mid+1,r,rson);

    pushup(k);
    return;
}
void update1(int l, int r, ll v, int k)
{
     if(l<=node[k].l&&node[k].r<=r)
     {
         node[k].lazy+=v;
         if(node[k].flag) node[k].flag+=v;
         node[k].sum+=(node[k].r-node[k].l+1)*v;
         return;
     }


     int mid=(node[k].l+node[k].r)/2;
     pushdown(k);

     if(l<=mid)update1(l,min(mid,r),v,lson);
     if(r>mid)update1(max(l,mid+1),r,v,rson);

     pushup(k);
}

void update2(int l, int r, int k)
{

    if(l<=node[k].l&&node[k].r<=r&&node[k].flag)
    {
        node[k].flag=sqrt(node[k].flag);
        node[k].sum=(node[k].r-node[k].l+1)*node[k].flag;
        return;
    }
    int mid=(node[k].l+node[k].r)/2;

    pushdown(k);

    if(l<=mid)update2(l,min(mid,r),lson);
    if(r>mid)update2(max(mid+1,l),r,rson);

    pushup(k);

}

ll getsum(int l,int r,int k)
{
   ll sum1=0;
   ll sum2=0;
   if(l<=node[k].l&&node[k].r<=r)
   {
       return node[k].sum;
   }
   pushdown(k);

   int mid=(node[k].l+node[k].r)/2;
   if(l<=mid)sum1=getsum(l,min(mid,r),lson);
   if(r>mid)sum2=getsum(max(mid+1,l),r,rson);

   return sum1+sum2;

}



int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt", "r", stdin);
    freopen("lala.txt", "w", stdout);
#endif
    T=Scan();
    while(T--)
    {
        n=Scan();
        m=Scan();
        for(int i = 1; i <= n; i++)
        {
            A[i]=Scan();
        }

        Build(1,n,1);
        while(m--)
        {
            op=Scan();
            l=Scan();
            r=Scan();

            if(op == 1)
            {
               x=Scan();
               update1(l,r,x,1);
            }
            else if(op == 2)
            {
              update2(l,r,1);
            }
            else if(op == 3)
            {
               Out(getsum(l,r,1));
               puts("");
            }
        }
    }


    return 0;
}

AC代码:

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const ll INF = 0x3f3f3f3f;
const ll maxn = 1e5 + 10;


ll Scan()//读入整数外挂.
{
    ll res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
void Out(ll a)    //输出外挂
{
    if(a > 9)
        Out(a / 10);
    putchar(a % 10 + '0');
    //prllf("\n");
}
/*1.加上一个值
  2.开根号
  3.计算总值
*/
int T;
int n, m;
int op;
int l, r;
ll x;
ll A[maxn];

class Node
{
public:
    int l;
    int r;
    ll sum;

    ll b;
    ll s;

    ll lazy;
    ll flag;//用flag来判断是否有整段的值都是一样的.
};

Node node[4 * maxn];

void pushup(int k)
{
    if(node[lson].flag == node[rson].flag && node[lson].flag)
    {
        node[k].flag = node[lson].flag;
    }
    else node[k].flag = 0;

    node[k].sum = node[lson].sum + node[rson].sum;

    node[k].b = max(node[lson].b, node[rson].b);
    node[k].s = min(node[lson].s, node[rson].s);
}

void pushdown(int k)
{

    if(node[k].flag)
    {
        node[lson].b = node[lson].s = node[lson].flag = node[k].flag;

        node[rson].b = node[rson].s = node[rson].flag = node[k].flag;

        node[lson].sum = (node[lson].r - node[lson].l + 1) * node[k].flag;
        node[rson].sum = (node[rson].r - node[rson].l + 1) * node[k].flag;

        node[k].lazy = 0;
    }
    if(node[k].lazy)
    {
        node[lson].sum += (node[lson].r - node[lson].l + 1) * node[k].lazy;
        node[rson].sum += (node[rson].r - node[rson].l + 1) * node[k].lazy;

        if(node[lson].flag)node[lson].flag += node[k].lazy;
        if(node[rson].flag)node[rson].flag += node[k].lazy;

        node[lson].b += node[k].lazy;
        node[lson].s += node[k].lazy;

        node[rson].b += node[k].lazy;
        node[rson].s += node[k].lazy;

        node[lson].lazy += node[k].lazy;
        node[rson].lazy += node[k].lazy;

        node[k].lazy = 0;
    }
    return;
}
void Build(int l, int r, int k)
{
    node[k].l = l;
    node[k].r = r;
    node[k].lazy = 0;
    node[k].flag = 0;

    if(l == r)
    {
        node[k].b=node[k].s=node[k].flag = node[k].sum = A[l];
        return ;
    }

    int mid = (l + r) / 2;

    Build(l, mid, lson);
    Build(mid + 1, r, rson);

    pushup(k);
    return;
}
void update1(int l, int r, ll v, int k)
{
    if(l <= node[k].l && node[k].r <= r)
    {
        node[k].lazy += v;
        if(node[k].flag) node[k].flag += v;
        node[k].sum += (node[k].r - node[k].l + 1) * v;

        node[k].b += v;
        node[k].s += v;
        return;
    }


    int mid = (node[k].l + node[k].r) / 2;
    pushdown(k);

    if(l <= mid)update1(l, min(mid, r), v, lson);
    if(r > mid)update1(max(l, mid + 1), r, v, rson);

    pushup(k);
}

void update2(int l, int r, int k)
{

    if(l <= node[k].l && node[k].r <= r)
    {
        if(node[k].flag)
        {
            node[k].flag = sqrt(node[k].flag);
            node[k].sum = (node[k].r - node[k].l + 1) * node[k].flag;

            node[k].b=node[k].flag;
            node[k].s=node[k].flag;

            return;
        }
        else if(node[k].b-node[k].s==1)
        {
            ll mb=node[k].b;
            ll ms=node[k].s;

            ll nb=sqrt(mb);
            ll ns=sqrt(ms);

            node[k].b=nb;
            node[k].s=ns;

            ll ml=node[k].sum-ms*(node[k].r-node[k].l+1);
            ll nl=(node[k].r-node[k].l+1)-ml;


            if( (nb-ns) == 1)
            {
                node[k].lazy+=(nb-mb);
                node[k].sum=nb*ml+ns*nl;
            }
            else
            {
                node[k].lazy=0;
                node[k].flag=nb;
                node[k].sum=(node[k].r-node[k].l+1)*nb;
            }
            return ;
        }

    }
    pushdown(k);

    int mid = (node[k].l + node[k].r) / 2;


    if(l <= mid)update2(l, min(mid, r), lson);
    if(r > mid)update2(max(mid + 1, l), r, rson);

    pushup(k);

}

ll getsum(int l, int r, int k)
{
    ll sum1 = 0;
    ll sum2 = 0;
    if(l <= node[k].l && node[k].r <= r)
    {
        return node[k].sum;
    }
    pushdown(k);

    int mid = (node[k].l + node[k].r) / 2;
    if(l <= mid)sum1 = getsum(l, min(mid, r), lson);
    if(r > mid)sum2 = getsum(max(mid + 1, l), r, rson);

    return sum1 + sum2;

}



int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt", "r", stdin);
    freopen("lala.txt", "w", stdout);
#endif
    T = Scan();
    while(T--)
    {
        n = Scan();
        m = Scan();
        for(int i = 1; i <= n; i++)
        {
            A[i] = Scan();
        }

        Build(1, n, 1);
        while(m--)
        {
            op = Scan();
            l = Scan();
            r = Scan();

            if(op == 1)
            {
                x = Scan();
                update1(l, r, x, 1);
            }
            else if(op == 2)
            {
                update2(l, r, 1);
            }
            else if(op == 3)
            {
                Out(getsum(l, r, 1));
                printf("\n");
            }
        }
    }


    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值