其他分享
首页 > 其他分享> > C20220805T2 赌徒

C20220805T2 赌徒

作者:互联网

设手中硬币的大小为 \(a\) 和 \(b\) ,对手硬币的两面是 \(a_i\) 和 \(b_i\) ,那么单次游戏的收益就是

\[\frac{1}{4}x_i(f(a,a_i)+f(a,b_i)+f(b,a_i)+f(b,b_i)) \]

其中 \(f(x,y)=(x\geq y)?\,1:-1\)

如果将式子的括号拆开,会发现单次游戏的收益分别与 \(a_i,b_i\) 有关,那么可以进一步推出,赌博中 \(a_i,b_i\) 对收益的影响可以分开计算,那么可以将 \(a_i,b_i\) 视为同一内容。同理,赌博中 \(a,b\) 的收益也可以分开计算、视为同一内容。

再来看上面的式子,由于上式中的 \(f\) 函数只和 \(x\geq y\) 有关,和 \(x,y\) 具体的取值无关,若我们将样例一的 \(a_i,b_i\) 放进一个数轴中用黑色来表示,红色部分为随便取的其他部分,分析一下它们之间取 \(a,b\) 其一时的优劣关系。

以2为例,若在取 \(a,b\) 中其一时取到2,那么绿色是 \(f\) 函数=1的部分,黄色是 \(f\) 函数取到-1的部分,这显然与取到1时完全相同,但是在计算收益时 \(1\times b\) 显然比 \(2\times b\) 要小,所以1更优。同理可以得到5比6优的结论。

其实还有一种情况,就是所有 \(f\) 函数值都取到-1,这种情况在样例1中没有体现,但存在,所以这种情况下 \(a,b\) 其一取到1时最优(因为是正整数)。

所以刚才证明了 \(a,b\) 一定取到1或 \(a_i,b_i\) ,并且可以分开计算收益,那么就可以着手做这一题了。对于每个可能的答案值 \(p\) 都求出一个 \(y_p\) ,表示在不考虑造硬币 \(ab\) 收益的情况下硬币取这个值的收益,具体 \(y_p\) 的求法就是 \(\sum_{i=1}^{p-1}x_i-\sum_{i=p+1}^{cnt}x_i\)。那么答案要求的就是 \(max\{y_a+y_b-ab\}\) ,这个问题就变成斜率优化问题。

然后维护一个丹钓战处理斜率的问题即可。

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define mp std::make_pair
#define pii std::pair<ll,ll>
#define chkmin(_A,_B) (_A=std::min(_A,_B))
#define chkmax(_A,_B) (_A=std::max(_A,_B))
class IO{
    public:
        inline char read(){
            static const int IN_LEN =1<<18|1;
            static char buf[IN_LEN],*s,*t;
            return (s==t)&&(t=(s=buf)+fread(buf, 1, IN_LEN, stdin)),(s==t)?-1:*s++;
        }
        template<typename _Tp>inline IO &operator >>(_Tp &x){
            static char c11, boo;
            for (c11=read(),boo=0;!isdigit(c11);c11=read()) {
                if (c11==-1)
                    return *this;
                boo|=(c11=='-');
            }
            for(x=0;isdigit(c11);c11=read())
                x=x*10+(c11^'0');
            if(boo)
                x=-x;
            return *this;
        }
        inline void push(const char &c) {
            putchar(c);
        }
        template<typename _Tp>inline IO &operator <<( _Tp x){
            if (x<0)
                x=-x,push('-');
            static _Tp sta[35];
            _Tp top=0;
            do{
                sta[top++]=x%10,x/=10;
            }while(x);
            while(top)
                push(sta[--top]+'0');
            return *this;
        }
        inline IO &operator <<(char lastChar){
            push(lastChar);
            return *this; 
        }
}FIO;
int n,tot;
ll pre[1000005],suf[1000005];
pii a[1000005];
int q[1000005],l,r;
ll ans=-1e14;
ll X(int _x){return a[_x].first;}
ll Y(int _x){return pre[_x]-suf[_x];}
double slope(int _x,int _y){return (double)(Y(_x)-Y(_y))/(double)(X(_x)-X(_y));}
ll res(int _x,int _y){return (Y(_x))+(Y(_y))-(X(_x)*(X(_y)));}
int main(){
	freopen("gamble.in","r",stdin);
	freopen("gamble.out","w",stdout);
	FIO>>n;
	for(int i=1;i<=n;++i){
		ll ai,bi,xi;
		FIO>>ai>>bi>>xi;
		a[++tot]=mp(ai*2,xi);
		a[++tot]=mp(bi*2,xi);
	}
	a[++tot]=mp(2,0);
	sort(a+1,a+tot+1);
	n=tot;
	for(int i=1;i<=n;++i)
		pre[i]=pre[i-1]+a[i].second;
	for(int i=n;i>=1;--i)
		suf[i]=suf[i+1]+a[i+1].second;
	l=1;r=1;
	q[1]=1;
	for(int i=2;i<=n;++i){
		while(l<r && res(i,q[r])<=res(i,q[r-1]))
			r--;
		chkmax(ans,res(i,q[r]));
		while(l<r && slope(q[r-1],q[r])<=slope(q[r],i))
			r--;
		q[++r]=i;  
	}
	for(int i=1;i<=n;++i)
		chkmax(ans,res(i,i));
	FIO<<ans;
	return 0;
}

标签:read,C20220805T2,tot,取到,赌徒,boo,c11,define
来源: https://www.cnblogs.com/zhouzizhe/p/16642687.html