hdu 4902 Nice Boat

简直要哭了。。你妹的。。这破题搞了老半天

题意呢  就是一开始时在连续区间内赋初值  然后有两种操作 

操作1  将给定区间内的值都换成另一个值

操作2  给定区间内 如果这个位置的值比给定的值大  就把这个值换成这两个数的公约数

因为这是完成所有操作之后输出最终的结果  采取延迟更新的方法减少不必要的操作

当需要更新的时候再去更新。。

比赛的时候 没写好  没有往下更新 今天就重新加了  不是说数据水的吗 我怎么就TLE了

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=100005;


int gcd(int a,int b)
{
    if(b)
        return  gcd(b,a%b);
    return a;
}

struct node
{
    int l,r;
    int num;
    int up;
    int mx;
};

node no[maxn*4];

void build(int l,int r,int k)
{
    if(l==r)
    {
        no[k].l=l;
        no[k].r=r;
        no[k].up=1;
        scanf("%d",&no[k].num);
        no[k].mx=no[k].num;
//        cout<<k<<" "<<no[k].num<<endl;
        return;
    }
    int mid=(l+r)/2;
    no[k].l=l;
    no[k].r=r;
    no[k].num=0;
    no[k].up=0;
    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
    no[k].mx=max(no[k*2].mx,no[k*2+1].mx);
}

void pushdown(int k)
{
    if(no[k].up)
    {
        no[k*2].up=no[k*2+1].up=no[k].up;
        no[k*2].num=no[k*2+1].num=no[k].num;
        no[k].up=0;
    }
}

void update1(int l,int r,int k,int n)
{
    if(l<=no[k].l&&no[k].r<=r)
    {
        no[k].num=n;
        no[k].up=1;
        return;
    }
    pushdown(k);
    int mid=(no[k].l+no[k].r)/2;
    if(r<=mid)  update1(l,r,k*2,n);
    else if(l>mid)  update1(l,r,k*2+1,n);
    else
    {
        update1(l,mid,k*2,n);
        update1(mid+1,r,k*2+1,n);
    }
}

void update2(int l,int r,int k,int n)
{
//    cout<<2222222<<endl;
    int mid2=(no[k].l+no[k].r)/2;
    if(l<=no[k].l&&no[k].r<=r)
    {
        if(no[k].up==1)
        {
            if(no[k].num>n)
            {
                no[k].num=gcd(no[k].num,n);
//                cout<<no[k].num<<"  "<<n<<endl;
                return;
            }
            else return;
        }
        else
        {
            if(no[k].mx<n)
                return;
            else
            {
                int mid=(no[k].l+no[k].r)/2;
                update2(l,mid,k*2,n);
                update2(mid+1,r,k*2+1,n);
            }

        }
    }
    pushdown(k);
    int mid=(no[k].l+no[k].r)/2;
    if(r<=mid)  update2(l,r,k*2,n);
    else if(l>mid)  update2(l,r,k*2+1,n);
    else
    {
        update2(l,mid,k*2,n);
        update2(mid+1,r,k*2+1,n);
    }
}


void search(int l,int r,int k)
{
    if(l<=no[k].l&&no[k].r<=r)
    {
        if(no[k].up)
        {
            for(int i=no[k].l;i<=no[k].r;i++)
                printf("%d ",no[k].num);
            return;
        }
        else
        {
            int midd=(no[k].l+no[k].r)/2;
            search(l,midd,k*2);
            search(midd+1,r,k*2+1);
        }
    }
    else
    {
        int mid=(no[k].l+no[k].r)/2;
        if(r<=mid)   search(l,r,k*2);
        else if(l>mid)  search(l,r,k*2+1);
        else
        {
            search(l,mid,k*2);
            search(mid+1,r,k*2+1);
        }
    }
}


int main()
{
    //freopen("input.txt","r",stdin);
    int tc;
    scanf("%d",&tc);
    while(tc--)
    {
        int n;
        scanf("%d",&n);
        build(1,n,1);
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(a==1)
            {
                update1(b,c,1,d);
            }
            else
                update2(b,c,1,d);
        }
        search(1,n,1);
        puts("");
    }
    return 0;
}


小澜写的代码高能。。真的挺快的。。就是没看太懂。。。哭瞎

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define LS p<<1, l, m
#define RS p<<1|1, m+1, r

const int MAXN = (int)1e5+5;

struct node {
    int t, l, r, x;

    node() {}
    node(int t, int l, int r, int x)
    : t(t), l(l), r(r), x(x) {}
}a[MAXN];

int MAX[MAXN<<2]; //着个区间最大直 max(MAX[l], MAX[r])
int last[MAXN<<2]; //这个区间的最迟1操作时间 min(last[l], last[r])
int lazy[MAXN<<2];
int id[MAXN];
int n, Q, len;

inline void pushUp(int p) {
    MAX[p] = max(MAX[p<<1], MAX[p<<1|1]);
    last[p] = min(last[p<<1], last[p<<1|1]);
}

inline void pushDown(int p) {
    if (lazy[p]) {
        last[p<<1] = last[p<<1|1] = last[p];
        MAX[p<<1] = MAX[p<<1|1] = MAX[p];
        lazy[p<<1] = lazy[p<<1|1] = true;
        lazy[p] = false;
    }
}

int gcd(int a, int b) {
    if (a<b) swap(a, b);
    if (b==0) return b;
    int t;
    while (b!=0) {
        t = b;
        b = a%b;
        a = t;
    }
    return a;
}

void build(int p, int l, int r) {
    lazy[p] = false;
    if (l==r) {
        id[l] = p;
        scanf("%d", &MAX[p]);
        last[p] = 0;
        return ;
    }

    int m = (l+r)>>1;
    build(LS);
    build(RS);
    pushUp(p);
}

void op1(int p, int l, int r, int L, int R, int x, int t) {
    if (L<=l&&r<=R) {
        MAX[p] = x;
        last[p] = t;
        lazy[p] = true;
        return ;
    }
    pushDown(p);
    int m = (l+r)>>1;
    if (L<=m) op1(LS, L, R, x, t);
    if (m <R) op1(RS, L, R, x, t);
    pushUp(p);
}

void op2(int p, int l, int r, int L, int R, int x, int t) {
    if (MAX[p]<=x || last[p]>t) return ; //
    if (l==r) { //叶子节点
        MAX[p] = gcd(MAX[p], x);
        return ;
    }
//    pushDown(p);
    int m = (l+r)>>1;
    if (L<=m) op2(LS, L, R, x, t);
    if (m <R) op2(RS, L, R, x, t);
    pushUp(p);
}

void dfs(int p, int l, int r) {
    if (l==r) {
//        printf("%d\n", MAX[p]);
        return ;
    }
    pushDown(p);
    int m = (l+r)>>1;
    dfs(LS);
    dfs(RS);
}

void solve() {
    len = 0;
    scanf("%d", &Q);
    int L, R, x, o;
    for (int i = 0; i < Q; i++) {
        scanf("%d%d%d%d", &o, &L, &R, &x);
        if (1==o) op1(1, 1, n, L, R, x, i);
        else a[len++] = node(i, L, R, x);
    }
    dfs(1, 1, n);
    for (int i = 0; i < len; i++)
        op2(1, 1, n, a[i].l, a[i].r, a[i].x, a[i].t);
    for (int i = 1; i <= n; i++)
        printf("%d ", MAX[id[i]]);
        puts("");
//    printf("%d\n", MAX[id[n]]);
}

int main() {
    #ifdef Phantom01
        freopen("1006.txt", "r", stdin);
    #endif // Phantom01

    int T;
    scanf("%d", &T);
    while (T--) {
      scanf("%d", &n);
      build(1, 1, n);
      solve();
    }

    return 0;
}


 然后找了别人的题解 借着思路又来了一发。。也是坑的不行。。唉。。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  100005
#define ls(x) (x<<1)
#define rs(x) ((x<<1)+1)
using namespace std;

struct node
{
    int l,r;
    int num;
    bool flag;//记录子节点中的值是不是一样的
    int v;
};

node no[MAXN*4];
int gcd(int a,int b)
{
    if(b)
        return  gcd(b,a%b);
    return a;
}

void pushup(int k)
{
    no[k].flag=(no[ls(k)].num==no[rs(k)].num)&&(no[ls(k)].flag)&&(no[rs(k)].flag);
    no[k].num=max(no[ls(k)].num,no[rs(k)].num);
//    no[k].num=no[ls(k)].num;
}

void pushdown(int k)
{
    if(no[k].v>=0)
    {
        no[ls(k)].v=no[rs(k)].v=no[k].v;
        no[ls(k)].num=no[rs(k)].num=no[k].v;
        no[k].v=-1;
    }
}

void build(int l,int r,int k)
{
    no[k].l=l;
    no[k].r=r;
    no[k].flag=0;
    no[k].v=-1;
    if(l==r)
    {
        int nn;
        scanf("%d",&nn);
        no[k].num=nn;
        no[k].flag=1;
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,ls(k));
    build(mid+1,r,rs(k));
    pushup(k);
}

void update1(int l,int r,int k,int n)
{
    if(l<=no[k].l&&no[k].r<=r)
    {
        no[k].flag=1;
        no[k].v=n;
        no[k].num=n;
        return;
    }
    pushdown(k);
    int mid=(no[k].l+no[k].r)/2;
    if(l<=mid)  update1(l,r,ls(k),n);//这两行写的方式啊啊啊啊
    if(r>mid)   update1(l,r,rs(k),n);
    pushup(k);
}

void update2(int l,int r,int k,int n)
{
    if(no[k].flag&&no[k].num<=n)  return;
    if(l<=no[k].l&&no[k].r<=r&&no[k].flag)
    {
        no[k].num=gcd(no[k].num,n);
        no[k].v=no[k].num;
        return;
    }
    pushdown(k);
    int mid=(no[k].l+no[k].r)/2;
    if(l<=mid)  update2(l,r,ls(k),n);//这两行写的方式啊啊啊啊
    if(r>mid)   update2(l,r,rs(k),n);
    pushup(k);
}

int ans(int k,int pos)
{
    if(no[k].l==no[k].r)
        return no[k].num;
    int mid=(no[k].l+no[k].r)/2;
    pushdown(k);
    if(pos<=mid)  return ans(ls(k),pos);
    else return ans(rs(k),pos);
}


int main()
{
freopen("ceshi.txt","r",stdin);
    int tc;
    scanf("%d",&tc);
    while(tc--)
    {
        int n;
        scanf("%d",&n);
        build(1,n,1);
        int q;
        scanf("%d",&q);
        for(int i=0; i<q; i++)
        {
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(a==1)
                update1(b,c,1,d);
            else  update2(b,c,1,d);
        }
        for(int i=1; i<=n; i++)
            printf("%d ",ans(1,i));
        puts("");
    }
    return 0;
}


线段树还得继续努力

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值