• Codechef March Challenge 2014——The Street


    The Street Problem Code: STREETTASolved

    https://www.codechef.com/problems/STREETTA

    Submit

    All submissions for this problem are available.

    Read problems statements in Mandarin Chinese and Russian.

    The String street is known as the busiest street in Codeland.
    Tourists from all over the world want to visit the street once they are in Codeland.
    The Chef owns N souvenir stores across the street (numbered from 1 to N).
    At the beginning there is no souvenir in any store, the Chef has some plans to add some new items.
    Each the Chef's plan is represented by 4 numbers: u v a b which mean an items with price b
    is added to the store u, an items with price a + b is added to the store u + 1 and so on.
    More formally, an item with price a * i + b is added to the store u + i for all (0 ≤ i ≤ v - u).

    In additional to the cost of the item itself, the tourist must pay some conservation fees as well.
    The Codeland regularly defines the new conservation fee. Each fee is represented by 4 numbers: u v a b which means
    the tourist buying any item in the store u + i will be charged a fee of i * a + b for all (0 ≤ i ≤ v - u).
    In the case that several conservation fees have effect on the same store, the customer needs to pay all of those fees.

    At some point of time, a tourist at store i asks you what is the largest amount of money they have to spend for
    a souvenir at that store (the amount of money includes the price of one of the souvenirs and all the conservation fees for that store).

    Input

    • The first line of the input contains two integers N and M represent the number of stores and the number of events
    • Each of the next M lines represents an event of three types below in the chronological order.
      • The new plan of the Chef: "1 u v a b".
      • The new conservation fee: "2 u v a b".
      • The query from tourist: "3 i".

    Output

    For each query from tourist, print in one line the corresponding answer.
    If there is no item at the ith store, print out "NA" (without quotes) as the answer.

    Constraints

    • 1 ≤ N ≤ 109
    • 1 ≤ M ≤ 3*105
    • For events of type 1: 1 ≤ u ≤ v ≤ N. |a|, |b| ≤ 109
    • For events of type 2: 1 ≤ u ≤ v ≤ N. |a|, |b| ≤ 104
    • For events of type 3: 1 ≤ i ≤ N

    Example

    Input:
    10 10
    3 5
    1 3 8 3 1
    3 5
    1 5 10 -8 2
    3 5
    3 10
    2 1 10 0 1
    3 6
    2 5 7 2 1
    3 6
    
    Output:
    NA
    7
    7
    -38
    11
    14

    题意:
    操作1:a数组的[l,r]对一个等差数列取大
    操作2:给b数组的[l,r]加一个等差数列
    操作3:询问 ai+bi

    数据范围:10^9,所以线段树动态开点
    等差数列最大值/和:一次函数
    对于操作2,线段树维护a的和,b的和,当加入ax+b时,直接加上就好
    对于操作1,分3种情况:
    1、区间本没有等差数列,直接加上
    2、区间原有的等差数列与现在的等差数列在区间内无交点,用大的直接覆盖
    3、区间原有的等差数列与现在的等差数列在区间内有交点,,那么一定有一个等差数列只能对当前区间的一半区间有影响,
    下传这个对一半区间有影响的等差数列,本区间保留另一个等差数列
    #include<cstdio>
    #include<algorithm> 
    #define INF (1LL<<62)
    #define N 300001
    using namespace std;
    struct node
    {
        long long a,b,end;
        bool have1,cross1;
        bool have2,cross2;
        long long maxna,maxnb;
    }tr[N*70];;
    int n,m,lc[N*70],rc[N*70],tot,cnt;
    int op,opl,opr,root;
    long long ans1,ans2,A,B;
    void flag(int k,int who,int l,int r);
    long long read()
    {
        long long x=0,f=1; char c=getchar();
        while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
        while(c>='0'&&c<='9') { x=x*10+c-'0' ; c=getchar(); }
        return x*f;
    }
    struct TREE
    {
        void add(int &k,int l,int r,long long a,long long b)
        {
            if(!k) 
            {
                k=++tot;
                tr[k].maxnb=-INF;
            }
            tr[k].cross1=true;
            if(l>=opl&&r<=opr) 
            {
                tr[k].b+=b; tr[k].a+=a;
                tr[k].have1=true;
                return;
            }
            int mid=l+r>>1;
            if(opl<=mid) add(lc[k],l,mid,a,b);
            if(opr>mid) add(rc[k],mid+1,r,a,A*(mid+1-opl+1-1)+B);
        }
        double meet(long long a1,long long b1,long long a2,long long b2)
        {
            if(a1!=a2) return 1.0*(b2-b1)/(a1-a2);
            return 0;
        }
        void down(int &k,long long aa,long long bb,int l,int r)
        {
            flag(lc[k],aa,bb,l,l+r>>1);
            flag(rc[k],aa,aa*((l+r>>1)+1-l)+bb,(l+r>>1)+1,r);
        }
        void flag(int &k,long long aa,long long bb,int l,int r)
        {
            if(!k) 
            {
                k=++tot;
                tr[k].maxnb=-INF;
            }
            tr[k].cross2=true;    
            tr[k].have2=true;
            if(l==r) 
            {
                tr[k].maxnb=max(tr[k].maxnb,bb);
                return; 
            }
            if(!tr[k].maxna&&!tr[k].maxnb)  { tr[k].maxna=aa; tr[k].maxnb=bb; return; }
            long long prea=tr[k].maxna,preb=tr[k].maxnb;
            long long preend=prea*(r-l+1-1)+preb;
            long long nowend=aa*(r-l+1-1)+bb;
            if(preb>=bb&&preend>=nowend) return;
            if(preb<=bb&&preend<=nowend) { tr[k].maxna=aa; tr[k].maxnb=bb; return; }
            double point=meet(tr[k].maxna,tr[k].maxnb,aa,bb);
            point+=l;
            if(point<1.0*(l+r>>1)) 
            {
                if(preb>bb)
                {
                     down(k,prea,preb,l,r);
                     tr[k].maxna=aa; tr[k].maxnb=bb;
                }
                else down(k,aa,bb,l,r);
            }
            else 
            {
                if(preend>nowend) 
                {
                    down(k,prea,preb,l,r);
                    tr[k].maxna=aa; tr[k].maxnb=bb;
                }
                else down(k,aa,bb,l,r);
            }
        }
        void maxn(int &k,long long aa,long long bb,int l,int r)
        {
            if(!k) 
            {
                k=++tot;
                tr[k].maxnb=-INF;
            }
            tr[k].cross2=true;
            if(l>=opl&&r<=opr)
            {
                flag(k,aa,bb,l,r);
                return;
            }
            if(tr[k].have2) down(k,tr[k].maxna,tr[k].maxnb,l,r);
            int mid=l+r>>1;
            if(opl<=mid) maxn(lc[k],aa,bb,l,mid);
            if(opr>mid) maxn(rc[k],aa,(mid+1-opl+1-1)*A+B,mid+1,r);
        }
        void query1(int k,int l,int r)
        {
            if(tr[k].have1) ans1+=tr[k].a*(opl-l+1-1)+tr[k].b;
            if(!tr[lc[k]].cross1&&!tr[rc[k]].cross1) return;
            int mid=l+r>>1;
            if(opl<=mid&&tr[lc[k]].cross1) query1(lc[k],l,mid);
            else if(opl>mid&&tr[rc[k]].cross1) query1(rc[k],mid+1,r);
        }
        void query2(int k,int l,int r)
        {
            if(tr[k].have2) ans2=max(ans2,tr[k].maxna*(opl-l+1-1)+tr[k].maxnb);
            if(!tr[lc[k]].cross2&&!tr[rc[k]].cross2) return;
            if(tr[k].have2) down(k,tr[k].maxna,tr[k].maxnb,l,r);
            int mid=l+r>>1;
            if(opl<=mid&&tr[lc[k]].cross2) query2(lc[k],l,mid);
            else if(opl>mid&&tr[rc[k]].cross2) query2(rc[k],mid+1,r); 
        }
    }Tree;
    int main()
    {
        n=read(); m=read();
        while(m--)
        {
            op=read();
            if(op==1)
            {
                opl=read(); opr=read(); A=read(); B=read();
                Tree.maxn(root,A,B,1,n);
            }
            else if(op==2)
            {
                opl=read(); opr=read(); A=read(); B=read();
                Tree.add(root,1,n,A,B);
            } 
            else
            {
                scanf("%d",&opl);
                ans2=-INF; Tree.query2(root,1,n);
                if(ans2==-INF) { puts("NA"); continue; }
                ans1=0; Tree.query1(root,1,n);
                printf("%lld
    ",ans1+ans2);
            }
        }
    } 

    三大错误:

    1、当前函数下传时,右区间首项为(mid+1-1)*a+b

       mid+1时右区间第一个,再-1因为等差数列首项为 a*0+b

    2、初始化:结构体内maxnb初始值为0,应该是无穷小,因为a,b可能为负数

       无穷小:-2e15 会WA,直接 1LL<<62

    3、down函数里下传k的等差数列后,k不能清0,因为k可能还有一个等差数列

  • 相关阅读:
    关于数据库 长度和小数点的关系和坑
    温故而知新,jquery选择器$=
    局域网访问本地localhost页面
    解决谷歌浏览器和360浏览器 input 自动填充淡黄色背景色的问题
    抢月饼 浏览器插件开发
    css 多行溢出
    ss服务待研究
    NUnit笔记
    5分钟实现VS2010整合NUnit进行单元测试
    vs2010中使用Nunit测试c#代码结果的正确性
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6855323.html
Copyright © 2020-2023  润新知