zoukankan      html  css  js  c++  java
  • 正睿2018.9.1提高2

    A 单调栈/凸壳

    题目链接

    题解

    对于二次函数提出一个x
    对于剩下的直线维护一个
    我们需要求出最大值上轮廓
    单调栈求上凸壳就好了

    code

    #include<cstdio> 
    #include<algorithm> 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9') { if(c == '-')f = -1;c = getchar();} 
    	while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
    	return x * f; 
    } 
    const int maxn = 500007; 
    int n,q; 
    struct fuc { 
    	int a,b; 
    } a[maxn],q1[maxn],q2[maxn]; 
    bool cmp(fuc a,fuc b) { 
    	return a.a == b.a ? a.b < b.b : a.a < b.a; 
    } 
    double cross(fuc a,fuc b) { 
    	return (double) (b.b - a.b) / (a.a - b.a); 
    } 
    int tp1 = 0,tp2 = 0; 
    long long ans[maxn * 7]; 
    void getcvx() { 
    	std::sort(a + 1,a + n + 1,cmp); 
    	for(int i = 1;i <= n;++ i) { 
    		while(tp1 && q1[tp1].a == a[i].a) tp1 --; 
    		while(tp1 > 1 && cross(a[i],q1[tp1]) <= cross(q1[tp1],q1[tp1 - 1]) ) tp1 --; 
    		q1[++ tp1] = a[i]; 
    	} 
    	for(int i = 1;i <= n;++ i) a[i].b = -a[i].b;
    	std::sort(a + 1,a + n + 1,cmp); 
    	for(int i = 1;i <= n;++ i) { 
    		while(tp2 && q2[tp2].a == a[i].a) tp2 --; 
    		while(tp2 > 1 && cross(a[i],q2[tp2]) <= cross(q2[tp2],q2[tp2 - 1]) ) tp2 --; 
    		q2[++ tp2] = a[i]; 
    	} 
    } 
    int main() { 
    	n = read(); q = read(); 
    	for(int i = 1;i <= n;++ i) a[i].a = read(),a[i].b = read(); 
    	getcvx(); 
    	for(int i = 1,x = 1;i <= 32323;++ i)  {
    		while(x < tp1 && cross(q1[x],q1[x + 1]) <= i) ++ x; 
    		ans[i + 32323] = 1ll * q1[x].a * i * i + 1ll * q1[x].b * i; 
    	} 
    	for(int i = 1,x = 1;i <= 32323;++ i) { 
    		while(x < tp2 && cross(q2[x],q2[x + 1]) <= i) ++ x; 
    		ans[32323 - i] = 1ll * q2[x].a * i * i + 1ll * (q2[x].b) * i; 
    	} 
    	for(int i = 1;i <= q;i += 1) { 
    		int k = read(); 
    		printf("%lld
    ",ans[k + 32323]); 
    	} 
    	return 0; 
    } 
    

    B 概率/期望

    题目链接

    题解

    答案可以看做是每一个元素被减的次数之和,可以计算每一个位置被减次数的期望之和
    第一个元素一定被减了(a_1)
    考虑一个位置i,当前有n个元素,那每个元素被减的概率都是(frac{1}{c})
    只关注元素(1)和元素(i),发现操作其他元素对他们没有影响,被减的概率仍相同
    于是这个问题等价于只有两个元素的问题
    对于两个元素的问题,可以看为从((a_1,a_i))出发,每次随机一个位置(-1),知道走到坐标轴上
    若停留在((0,a)),对答案的贡献为(a_i - a),若停留在((a,0)),对答案的贡献为a_i
    可以写出贡献式子

    [sum_{i=0}^{a_i-1}frac{inom{a_1-1+i}{i}}{2^{a_1+i}}i+a_ileft(1-sum_{i=0}^{a_i-1}frac{inom{a_1-1+i}{i}}{2^{a_1+i}} ight) ]

    可以对于(0 - max(ai))做前缀和,前后的概率式等价,最后可以线性计算答案

    code

    #include<cstdio> 
    #include<algorithm> 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9') c = getchar(); 
    	while(c <= '9' && c >= '0') x = x * 10 + c - '0' ,c = getchar(); 
    	return x * f; 
    } 
    #define LL long long 
    const int mod = 323232323; 
    const int maxn = 200007; 
    int n,m,a1,a[maxn]; 
    int inv[maxn],inv2[maxn]; 
    int fac[maxn]; 
    inline int fstpow(int x,int k) {
    	int ret = 1; 
    	for(;k;k >>= 1,x = 1ll * x * x % mod) if(k & 1)ret = 1ll * ret * x % mod; 
    	return ret; 
    } 
    inline int C(int n,int m) { 
    	return (1ll * fac[n] * inv[m] % mod) * inv[n - m] % mod; 
    } 
    void pre() {
    	fac[1] = fac[0] = 1; 
    	for(int i = 2;i <= m;++ i) fac[i] = 1ll * fac[i - 1] * i % mod; 
    	inv[m] = fstpow(fac[m],mod - 2); 
    	for(int i = m - 1;~ i;-- i) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod; 
    	//inv[2^i]
    	int t = fstpow(2,mod - 2); inv2[0] = 1; 
    	for(int i = 1;i <= m;++ i) inv2[i] = 1ll * inv2[i - 1] * t % mod; 
    } 
    inline void add(int &x,int y) { 
    	x = x + y >= mod ? x + y - mod : x + y; 
    } 
    int p[maxn],f[maxn]; 
    int main() { 
    	n = read();int mx = 0; 
    	for(int i = 1;i <= n;++ i) a[i] = read(),mx = std::max(mx,a[i]);  
    	a1 = a[1], m = a1 + mx; 
    	pre(); 
    	p[0] = inv2[a1]; 
    	for(int i = 1;i <= m;++ i) { 
    		p[i] = 1ll * C(a1 + i - 1,i) * inv2[a1 + i] % mod; 
    		f[i] = 1ll * i * p[i] % mod; 	
    		add(p[i],p[i - 1]); 
    		add(f[i],f[i - 1]); 
    	} 
    	int ans = a1; 
    	for(int i = 2;i <= n;++ i) {
    		int t = (f[a[i]] + 1ll * a[i] * (mod + 1 - p[a[i]]) % mod) % mod; 
    		add(ans,t); 
    	} 
    	printf("%d
    ",ans); 
    	
    	return 0; 
    } 
    

    C

    题目链接

    题解

    code

  • 相关阅读:
    CodeForces 659F Polycarp and Hay
    CodeForces 713C Sonya and Problem Wihtout a Legend
    CodeForces 712D Memory and Scores
    CodeForces 689E Mike and Geometry Problem
    CodeForces 675D Tree Construction
    CodeForces 671A Recycling Bottles
    CodeForces 667C Reberland Linguistics
    CodeForces 672D Robin Hood
    CodeForces 675E Trains and Statistic
    CodeForces 676D Theseus and labyrinth
  • 原文地址:https://www.cnblogs.com/sssy/p/9577018.html
Copyright © 2011-2022 走看看