hdu 4902 线段树双标记类型题

来源:互联网 发布:手机淘宝怎样朋友代付 编辑:程序博客网 时间:2024/05/29 14:16

比赛时没敲出来,似乎现在敲得还是不好

后来找了份题解,http://www.cnblogs.com/qq1012662902/p/3883614.html  600多msAC  很高效了


参考了之后写了代码  近期在重写一遍

</pre><pre name="code" class="cpp">#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <iostream>using namespace std;#define ls(rt) rt*2#define rs(rt) rt*2+1#define ll long long#define rep(i,s,e) for(int i=s;i<e;i++)#define repe(i,s,e) for(int i=s;i<=e;i++)#define IN(s) freopen(s,"r",stdin)const int MAXN = 100000+100;int gcd(int a, int b){    if(!a)return b;////    if(!b)return a;    return gcd(b,a%b);}int num[MAXN];struct Node{    int l,r;    int mx,val;    //mx记录最大值,用于剪枝    //val为-1是没有lazy,否则存储需要更新的值v--操作1    //注意因为更新的值是大于等于0的,所以可以这么用}nodes[MAXN*4];void pushup(int rt){    nodes[rt].mx=max(nodes[ls(rt)].mx,nodes[rs(rt)].mx);}void build(int rt, int l, int r){    nodes[rt].l=l;    nodes[rt].r=r;    nodes[rt].mx=0;    nodes[rt].val=-1;    if(l == r)    {        nodes[rt].mx=nodes[rt].val=num[l];        return;    }    int mid=(l+r)/2;    build(ls(rt),l,mid);    build(rs(rt),mid+1,r);    pushup(rt);}void modify(int rt,int v)//2操作{    if(nodes[rt].mx<=v)return;    if(nodes[rt].val!=-1)//仍然更新到段--到仅仅有一种更新lazy标记    {        nodes[rt].mx=nodes[rt].val=gcd(nodes[rt].val,v);        //nodes[rt].val=-1;        return;    }    modify(ls(rt),v);    modify(rs(rt),v);    pushup(rt);}void update(int rt, int l, int r,int op,int v){    //找到区间之后,根据操作做更新    //一种操作的话,当找到对应的    //区间(nodes[rt].l==l && nodes[rt].r==r)之后,    //只标记而不往下更新,直到下次update到这次才将这次的pushdown    //此题中,操作一是赋值,会覆盖操作二,所以直接操作    //如果是操作二,查看之前是不是已经有lazy操作,有的话,先做之前的lazy,    //直到达到一个结点,该节点没有做过lazy标记,那么标记这个节点,停止update‘    if(nodes[rt].l==l && nodes[rt].r==r)    {        if(op==1)        {            nodes[rt].val=v;            nodes[rt].mx=v;//该区间所有的值都变成了v,所以最大值为v        }        else        {            modify(rt,v);        }        return;    }    //pushdown    if(nodes[rt].val!=-1)    {        //此处把mx也更新了,因为gcd(a,b)<=a&&gcd(a,b)<=b        //又因为题目中说了,当要更新的val<num[i]时才更新num[i]为gcd();        //        nodes[ls(rt)].mx=nodes[rs(rt)].mx=nodes[rt].val;        nodes[ls(rt)].val=nodes[rs(rt)].val=nodes[rt].val;        nodes[rt].val=-1;    }    int mid=(nodes[rt].l+nodes[rt].r)/2;    if(r<=mid)update(ls(rt),l,r,op,v);    else    {        if(l>mid)            update(rs(rt),l,r,op,v);        else        {            update(ls(rt),l,mid,op,v);            update(rs(rt),mid+1,r,op,v);        }    }    pushup(rt);}void dfs(int rt){    if(nodes[rt].l==nodes[rt].r)    {        num[nodes[rt].l]=nodes[rt].val;        return;    }    if(nodes[rt].val!=-1)    {        nodes[ls(rt)].val=nodes[rs(rt)].val=nodes[rt].val;        nodes[rt].val=-1;    }    dfs(ls(rt));    dfs(rs(rt));}int main(){    //IN("hdu4902.txt");    int ncase,n,q,l,v,r;    int op;    scanf("%d",&ncase);    while(ncase--)    {        scanf("%d",&n);        for(int i=1;i<=n;i++)            scanf("%d",&num[i]);        build(1,1,n);        scanf("%d",&q);        while(q--)        {            scanf("%d%d%d%d",&op,&l,&r,&v);            update(1,l,r,op,v);        }        dfs(1);        for(int i=1;i<=n;i++)            printf("%d ",num[i]);        putchar('\n');    }    return 0;}


2 0
原创粉丝点击