zoukankan      html  css  js  c++  java
  • E-card

    E-card

    题目描述

     

    两个人各有n张牌

    第一个人有n-1张平民和1张皇帝

    第二个人有n-1张平民和1张奴隶

    每次选择一张牌 进行对决 如果都是平民则平局

    皇帝赢平民 奴隶赢皇帝 平民赢奴隶(显然只会有一局会不是平局 那局就是决胜局)

    现在你是奴隶方 已知皇帝方是个沙茶 每次会在现有的手牌中随便选一张出 问你的最优决策(即在哪次出奴隶)

    本来这是个沙茶问题 但是皇帝方有一天觉醒了 他不再每次随便选一张出 而是第i次以一个概率p选择出皇帝 1-p出平民

    皇帝方对第i次出皇帝有估算一个收益vi(初始为0)

    第i次出皇帝的概率是vi/Σv

    当然皇帝方会改变他的看法(根据你的表情0 0)但是因为他是沙茶 他对他的猜想又不是很确定╮(╯_╰)╭ 所以他会在心里想一个模拟收益数组u(初始为0)

    每次选择4个数L,R,a,b对于i (L<=i<=R)

    u[i]更新为max(u[i], (i – L) * a + b)

    在某个时刻他会确定他某次的猜想比较好 然后他会让v[i]=u[i] 这时候你会想知道你当前应该在哪出奴隶(如果多个最优解 输出最小的那个)

     

     

    输入

     

    第一行三个整数 n,m

    代表n张牌 m次操作

    接下来m行

    如果第一个数是1 则后面跟4个数代表L,R,a,b

    如果第一个数是2 则后面跟1个数i 代表把v[i]赋值为u[i] 并输出当前最优位置

    对于30%的数据 n <= 10^5, m <= 1000

    对于100%的数据n<=10^9, m<=100000, 1 <= L <= R <= n, |a,b|<=10^9

     

     

    输出

     

    每行一个数表示询问的结果

     

     

    样例输入

    
    1 5 10 -8 2
    2 4
    1 3 8 3 1
    2 4
    2 5
    2 6
    2 7
    2 8

    样例输出

    1
    4
    5
    6
    7
    8

     

     

     

    怪题,浪费一下午

    solution

    对于 (i – L) * a + b

    把它化为i*a-L*a+b 即一段一次函数(k=a,b=-L*a+b)

    把区间(L,R)打上标记(k,b)

    考虑如何处理已有标记的区间

    假设有标记(k1,b1)

    我要加入(k2,b2)

    不妨设k1>k2

    分类:

    1.若b1>b2   保留(k1,b1)

     

    2,b1<b2  这就麻烦了

    k1*x+b1-k2*x-b2

    t=(b2-b1)/(k1-k2)(取下整)

    所以x>t 取k1,b1

    x<=t k2,b2

    再分类

    t<l  取k1,b1

     

    t>=r 取k2,,b2

     

    l<t<=mid  左儿子全取k2,b2,右儿子未知

    则 k保留k2,b2,递归更新右儿子

     

    mid<t<r 右儿子全取k1,b1,左儿子未知

    则 k保留k1,b1 递归更新左儿子

     

    查询时,把i到根的路径取max

    这样就可以了。

     

    因为,对于一个点,可能造成贡献的答案,一定在i到根的路径上。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    long long n,m,pl,mp,tot;
    long long maxv,li,ri,a1,b1;
    struct no{
        long long k,b;
    };
    struct node{
        no x;long long ls,rs;
    }tree[100005*42];
    void ma(long long &k){
        if(!k)k=++tot;
    }
    void orz(long long k,long long L,long long R,no a){ 
        if(!tree[k].x.k)tree[k].x=a;
        else {  
            if(a.k>tree[k].x.k)swap(a,tree[k].x);
            if(a.b<=tree[k].x.b){return;}//k1>k2 b1>b2
            if(a.k==tree[k].x.k){tree[k].x.b=max(tree[k].x.b,a.b);return;}
            long long k1=a.k,k2=tree[k].x.k,b1=a.b,b2=tree[k].x.b;
            long long t=(b2-b1)/(k1-k2);
            long long mid=L+R>>1;
            if(t<L){return;}//k1 b1
            if(t>=R){tree[k].x=a;return;}//k2 b2
            if(t<=mid){//mid+1~r  k1b1
                ma(tree[k].ls);
                orz(tree[k].ls,L,mid,a);
            }
            if(t>mid){//l~mid k2b2
                swap(a,tree[k].x);
                ma(tree[k].rs);
                orz(tree[k].rs,mid+1,R,a);
            }
        }
    }
    void lian(long long k,long long L,long long R,no a){
        if(L>=li&&R<=ri){
            orz(k,L,R,a);
            return;
        }
        long long mid=L+R>>1;
         
        if(li<=mid){
            ma(tree[k].ls);
            lian(tree[k].ls,L,mid,a);
        }
        if(ri>mid){
            ma(tree[k].rs);
            lian(tree[k].rs,mid+1,R,a);
        }
    }
    long long ask(long long k,long long L,long long R){
        if(!k)return 0;
        if(L==R){
            return tree[k].x.k*pl+tree[k].x.b;
        }
        long long mid=L+R>>1;
        long long t=0;
        if(tree[k].x.k)t=max(t,tree[k].x.k*pl+tree[k].x.b); 
        if(pl<=mid)t=max(t,ask(tree[k].ls,L,mid));
        else t=max(t,ask(tree[k].rs,mid+1,R));
        return t;
    }
    int main()
    {
        cin>>n>>m;tot=1;
        maxv=0;mp=1;
        for(long long i=1;i<=m;i++){
            long long op;
            scanf("%lld",&op);
            if(op==1){
                scanf("%lld%lld%lld%lld",&li,&ri,&a1,&b1);
                no ne;ne.k=a1,ne.b=-a1*li+b1;
                //cout<<ne.k<<' '<<ne.b<<endl;
                lian(1,1,n,ne);
            }
            else {
                scanf("%lld",&pl);
                long long t=ask(1,1,n);
                if(t>maxv)maxv=t,mp=pl;
                if(t==maxv)mp=min(mp,pl);
                printf("%lld
    ",mp);
            }
        }
        return 0;
    }
     
  • 相关阅读:
    设计模式之单例模式
    设计模式之原型模式
    设计模式之建造者模式
    设计模式之抽象方法模式
    设计模式之简单工厂模式
    java中内存分配
    java引用类型
    Oracle
    Oracle
    Oracle
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358885.html
Copyright © 2011-2022 走看看