HDU 4902 Nice boat 线段树+离线

据说暴力也过了。还傻逼地写了这么长。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
using namespace std;
#define ll long long
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Val(x) tree[x].val
#define Lazy(x) tree[x].lazy
#define Num(x) tree[x].num
const ll oo = (ll)(-1e15);
inline ll Mid(ll x, ll y){return (x+y)>>1;}
inline ll gcd(ll x, ll y){
    if(x>y)swap(x,y);
    while(x){
        y%=x;
        swap(x,y);
    }
    return y;
}
#define N 100500
struct qqq{
    ll op, l, r, val;
}Q[N];
ll n, a[N];
struct node{
    ll l, r;
    ll lazy, num;
}tree[N<<2];
void push_down(ll id){
    if(tree[id].l == tree[id].r) return;
    if(Num(id)>0){
        Num(L(id)) = Num(R(id)) = Num(id);
    }
    if(Lazy(id) == oo) return;
    Lazy(L(id)) = Lazy(R(id)) = Lazy(id);
    Lazy(id) = oo;
}
void push_up(ll id){
    if(Num(L(id)) != Num(R(id)))
    {
        Num(id) = -1;
    }
    else if(Num(L(id)) == Num(R(id)))Num(id) = Num(L(id));
}
void build(ll l, ll r, ll id){
    tree[id].l = l, tree[id].r = r;
    Lazy(id) = oo;
    Num(id) = 0;
    if(l == r)
    {
        Lazy(id) = a[l];
        return;
    }
    ll mid = Mid(l, r);
    build(l, mid, L(id));
    build(mid+1, r, R(id));
}
void updata1(ll l, ll r, ll val, ll num, ll id){
    push_down(id);
    if(Num(id) > num)return ;
    if(l == tree[id].l && tree[id].r == r && Num(id) == 0)
    {
        Lazy(id) = val;
        Num(id) = num;
        return;
    }
    ll mid = Mid(tree[id].l, tree[id].r);
    if(mid < l)
        updata1(l, r, val, num, R(id));
    else if(r <= mid)
        updata1(l, r, val, num, L(id));
    else {
        updata1(l, mid, val, num, L(id));
        updata1(mid+1, r, val, num, R(id));
    }
    push_up(id);
}
void updata2(ll l, ll r, ll val, ll num, ll id){
    push_down(id);
    if(Num(id) > num)return ;
    if(l == tree[id].l && tree[id].r == r && Num(id)!=-1)
    {
        if(Lazy(id)!=oo)
        {
            if(Lazy(id) > val)
            Lazy(id) = gcd(Lazy(id), val);
            return ;
        }
    }
    ll mid = Mid(tree[id].l, tree[id].r);
    if(mid < l)
        updata2(l, r, val, num, R(id));
    else if(r <= mid)
        updata2(l, r, val, num, L(id));
    else {
        updata2(l, mid, val, num, L(id));
        updata2(mid+1, r, val, num, R(id));
    }
    if(Lazy(L(id)) == Lazy(R(id)))
        Lazy(id) = Lazy(L(id));
    else Lazy(id) = oo;
}
void query(ll id){
    push_down(id);
    if(tree[id].l == tree[id].r)
    {
        printf("%I64d ", Lazy(id));
        return ;
    }
    ll mid = Mid(tree[id].l, tree[id].r);
    query(L(id));
    query(R(id));
}
int main(){
    ll i, l, r, T, que, op, val; cin>>T;
    while(T--){
        cin>>n;
        for(i = 1; i <= n; i++)scanf("%I64d",&a[i]);
        build(1, n, 1);
        cin>>que;
        for(i = 1; i <= que; i++)scanf("%I64d %I64d %I64d %I64d", &Q[i].op, &Q[i].l, &Q[i].r, &Q[i].val);
        for(i = que; i; i--)
            if(Q[i].op == 1)
            {
                updata1(Q[i].l, Q[i].r, Q[i].val, i, 1);
            }
        for(i = 1; i <= que; i++)
            if(Q[i].op == 2 && Q[i].op)
            {
                updata2(Q[i].l, Q[i].r, Q[i].val, i, 1);
            }
            query(1);
            puts("");
    }
    return 0;
}
时间: 2024-10-13 02:05:35

HDU 4902 Nice boat 线段树+离线的相关文章

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

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

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

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

题意:给一个数字序列,第一类操作是将[l,r]内的数全赋为x ,第二类操作是将[l,r]中大于x的数赋为该数与x的gcd,若干操作后输出整个序列. 解法: 本题线段树要维护的最重要的东西就是一个区间内所有数是否相等的标记.只维护这个东西都可以做出来. 我当时想歪了,想到维护Max[rt]表示该段的最大值,最大值如果<=x的话就不用更新了,但是好像加了这个“优化”跑的更慢了. 我想大概是因为如果两个子树最大值或者整个两个子树的数不完全相等的话,根本不能直接下传这个值或者下传gcd,因为你不知道要更

hdoj 4901 The Romantic Hero DP hdoj 4902 Nice boat 线段树

惨遭丽洁乱虐..这一场也是比得乱七八糟的,4902本是丽洁定义比较难的题,结果数据随机的,被许多暴力水过了..4905考察的是四边形不等式优化,但是这道题的dp方程实际上不满足该优化的条件..朴素的o(n^3)会超时,所以这题目前是没有正解了..我还写了个这题的贪心,强度挺高,可以对大概一半数据,错的误差也只有个位数,还揪出官方第五个数据..朴素dp和贪心跑这个数据都比官方数据多了1,也就证明这题不满足四边形不等式优化的条件.. http://acm.hdu.edu.cn/showproblem

hdu 4417 Super Mario (线段树+离线)

题意: n个砖块,第i个砖块的高度是hi. m个query,每个query的格式:L R H (输出[L,R]中有多少个hi小于等于H[即玛里奥能跳过多少块砖]) 数据范围: 1 <= n <=10^5, 1 <= m <= 10^5 Next line contains n integers, the height of each brick, the range is [0, 1000000000]. ( 0 <= L <= R < n 0 <= H &

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 多校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的也给搞了 还想过说先存起来所有

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