HDU 4902 Nice boat 多校4 线段树

给定n个数

第一个操作和普通,区间覆盖性的,把l-r区间的所有值改成固定的val

第二个操作是重点,输入l r x 把l-r区间的所有大于x的数,变成gcd(a[i],x) a[i]即指满足条件的序列上的数值

最后才输出所有值

当时苦思这个地方如何优化,想着不可能单点去更新吧,但是区间gcd,不能保存下来,一来他是要>x才有效,本来聪哥想了一种先把各种x gcd一遍,最后在push下去,发现不行,就是因为他对>x才有效,你在区间就直接gcd了,那不是把不该gcd的也给搞了

还想过说先存起来所有的x,当然也有限制条件,就是说比较大的就不要了,因为gcd越搞越小,你后面来个大的x没意义,最后再push下去。。。我这样敲了一下,wa了,后来分析下,觉得这个根顺序还是有关系,我直接记录完,push下去没讲顺序 还是有问题的

后来居然claration有人讲他暴力过的,。。我也是醉了

当然不是真的完全暴力,还是要优化的,一个是大家都做了的,就是利用第一个操作,如果某区间都是一个值,那gcd直接在这个区间跟这个值弄一下,就可以了,不用再往下走了。

我还做了另一个优化,就是记录每个区间的最大值,要是当前x走到某个区间,发现比最大值还>=,那直接return即可,没有任何意义

后来终于是AC了,注意点细节,没什么太难的。不过后来讨论到为什么可以这样不超时,聪哥说有个lamp定理,可以证明每个int整数,最多不超过31次gcd就会变成1(感觉像二分一样,聪哥说这玩意衰变得很快),也就是说,我有了上述优化之后,实际每个数最多只要31次更新到底即可,n个数只要n*31次更新到底即可,其他的都会被优化掉,所以为什么不会超时。。。虽然我不明白这个31次是怎么来的,不过如果这个是成立的,那就完全可以解释这个算法了。,明天还去跟聪哥讨论一下这个lamp定理,看下到底是怎么证明出31次的

后来我AC之后又想优化一下,把原因的1操作的懒惰标记iss想变成状态型的,比如单个节点iss永远是1,表示他就是被自己覆盖了嘛,但是会WA,就是说,你状态型的,你上面的结构也要保持该状态,上面没处理好,很麻烦的。。所以不建议是这么混着来,懒惰标记就是懒惰标记,别混成状态标记了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define LL __int64
using namespace std;
const int N=100000+10;
int A[N];
int setv[N<<2],iss[N<<2],d[N<<2];
int gcd(int a,int b)
{
    if (abs(a)<abs(b)) swap(a,b);
    while (b)
    {
        int tmp=a;
        a=b;
        b=tmp%b;
    }
    return a;
}
int n;
void up(int rt)
{
    d[rt]=max(d[rt<<1],d[rt<<1|1]);
    if (setv[rt<<1]==setv[rt<<1|1] && iss[rt<<1] && iss[rt<<1|1]){
        setv[rt]=setv[rt<<1];
        iss[rt]=1;
    }
}
void build(int rt,int l,int r)
{
    iss[rt]=setv[rt]=0;
    if (l>=r)
    {
        d[rt]=A[l];
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    up(rt);
}
void pushdown(int rt,int l,int r)
{
    if (l>=r) return;
    if (iss[rt]){
        d[rt]=setv[rt];
        setv[rt<<1]=setv[rt<<1|1]=setv[rt];
        d[rt<<1]=d[rt<<1|1]=setv[rt];
        iss[rt<<1]=iss[rt<<1|1]=iss[rt];
        iss[rt]=0;

    }
}
void fix(int L,int R,int val,int rt,int l,int r)
{
    if (L<=l && r<=R)
    {
        iss[rt]=1;
        setv[rt]=val;
        d[rt]=val;
        if (l==r) A[l]=val;
        return;
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    if (R<=mid) fix(L,R,val,lson);
    else
    if (L>mid)  fix(L,R,val,rson);
    else{
        fix(L,R,val,lson);
        fix(L,R,val,rson);
    }
    up(rt);
}
void fgcd(int L,int R,int val,int rt,int l,int r)
{
    if (val>=d[rt]) return;
    if (iss[rt] && L<=l && r<=R && l<r){
        if (setv[rt]>val){
            setv[rt]=gcd(setv[rt],val);
            d[rt]=setv[rt];
        }
        return;
    }
    if (L==l && r==R && l==r)
    {
        if (iss[rt]){
            A[l]=setv[rt];
            d[rt]=A[l];
            iss[rt]=0;
        }
        if (A[l]>val){
            A[l]=gcd(A[l],val);
            d[rt]=A[l];
        }
        return;
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    if (R<=mid) fgcd(L,R,val,lson);
    else
    if (L>mid) fgcd(L,R,val,rson);
    else
    {
        fgcd(L,mid,val,lson);
        fgcd(mid+1,R,val,rson);
    }
    up(rt);
}
void merges(int rt,int l,int r)
{
    if (l>=r)
    {
        if (iss[rt]){
            A[l]=setv[rt];
            d[l]=setv[rt];
            iss[rt]=0;
        }
        return;
    }
    int mid=(l+r)>>1;
    pushdown(rt,l,r);
    merges(lson);
    merges(rson);
}
int main()
{
    int t,q,op;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            scanf("%d",&A[i]);
        }
        build(1,1,n);
        scanf("%d",&q);
        while (q--)
        {
            int a,b,x;
            scanf("%d",&op);
            scanf("%d%d%d",&a,&b,&x);
            if (op==1){
                fix(a,b,x,1,1,n);
            }
            else{
                fgcd(a,b,x,1,1,n);
            }
        }
        merges(1,1,n);
        for (int i=1;i<=n;i++){
            printf("%d ",A[i]);
        }
        puts("");
    }
    return 0;
}

  

HDU 4902 Nice boat 多校4 线段树,布布扣,bubuko.com

时间: 2024-12-27 00:05:01

HDU 4902 Nice boat 多校4 线段树的相关文章

多校第4场 HDU 4902 Nice boat 线段树

思路:这题比赛的时候宝哥说的思路我觉得对的,就是当是2操作的时候,先把数放到数组里,最后查询输出的时候再统一计算,不过那时敲得烂死了,debug了两天,靠-- 上午写的vector在pushDown的时候又忘了clear了,然后MLE了一早上,尼玛,还以为用的数组太大超了,然后又改成结构体,还是MLE,最后把别人的代码交上去发现没MLE,疯了一中午,最后无聊的时候才发现这个错误,尼玛--发现自己调试怎么变得这么弱了呢-- 还有一个需要注意的问题是1与2操作的处理上比较容易出错,这也是我WA了一下

HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是把区间 (l,r) 中大于x的数跟 x 做gcd操作. 线段树区间更新的题目,每个节点保存一个最大和最小值,当该节点的最大值和最小值相等的时候表示这个区间所有的数字都是相同的,可以直接对这个区间进行1或2操作, 进行1操作时,当还没有到达要操作的区间但已经出现了节点的最大值跟最小值相等的情况时,说明

hdu 4902 Nice boat(2014多校训练第4场 1006)

Nice boat                                                                           Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description There is an old country and the king fell in love with a d

HDU 4902 Nice boat(线段树)

HDU Nice boat 题目链接 题意:给定一个序列,两种操作,把一段变成x,把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 思路:线段树,每个结点多一个cover表示该位置以下区间是否数字全相同,然后每次延迟操作,最后输出的时候单点查询即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1

HDU 4902 Nice boat(线段树 区间更新)

Nice boat 大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x  2:把区间中大于x的数变成gcd(a[i], x),最后输出序列. 思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用. 1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8

HDU 4902 Nice boat(数据结构-线段树)

Nice boat Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and c

HDU 4902 Nice boat 成段线段树

操作1 的时候标记deng[rt]表示下面一段数都是与当前节点的值相同 下次操作2时直接对有deng标记的节点gcd更新 (可能还可以更简单) #include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #incl

hdu 4902 Nice boat(线段树区间修改,输出最终序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his peopl

HDU - 4902 Nice boat

Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can't refuse any re