zoukankan      html  css  js  c++  java
  • 2021-06-25 集训题解

    T1 硬币游戏

    题目传送门

    Description

    Solution

    不难看出,可以将 (b_i) 加上 (a_i),那么可以视作两种操作,一个是加上权重为 (1)(a_i),另一个是加上权重为 (2)(b_i),然后你发现限制没了,只需要权重 (=k),直接排序之后乱搞就好了。

    代码就不放了。

    T2 序列计数

    题目传送门

    Description

    Solution

    可以设 (f_{S,x}) 表示字符串 (S) 中以 (x) 结尾的本质不同子序列个数。

    然后你发现转移可以写成矩阵形式,而且可逆,所以就直接预处理出前缀积和前缀逆即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define mod 1000000007
    #define MAXN 500005
    
    template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
    template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
    template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    template <typename T> void chkmax (T &a,T b){a = max (a,b);}
    template <typename T> void chkmin (T &a,T b){a = min (a,b);}
    
    #define up 10
    int mul (int a,int b){return 1ll * a * b % mod;}
    int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
    void Add (int &a,int b){a = a + b >= mod ? a + b - mod : a + b;}
    
    char s[MAXN];
    int n,q,sum[11],tag[11],A[11][11],B[11][11],f1[MAXN][11],f2[MAXN][11];
    
    signed main(){
        freopen ("sequence.in","r",stdin);
        freopen ("sequence.out","w",stdout);
        scanf ("%s",s + 1),n = strlen (s + 1);
        for (Int i = 0;i <= up;++ i) A[i][i] = B[i][i] = sum[i] = 1;f2[0][up] = 1;
        for (Int i = 1;i <= n;++ i){
        	int c = s[i] - 'a';
        	for (Int j = 0,t;j <= up;++ j){
        		t = A[j][c],A[j][c] = sum[j],f1[i][j] = sum[j] = dec (mul (sum[j],2),t);
        		t = B[c][j],B[c][j] = dec (mul (B[c][j],2),tag[j]),f2[i][j] = dec (B[up][j],tag[j] = t);
    		}
    	}
    	read (q);
    	while (q --> 0){
    		int l,r,ans = 0;read (l,r);
    		for (Int i = 0;i <= up;++ i) Add (ans,mul (f1[r][i],f2[l - 1][i]));
    		write (dec (ans,1)),putchar ('
    ');
    	}
    	return 0;
    }
    

    T3 最大面积

    题目传送门

    Description

    Solution

    可以想到的是,对于一个区间 ([L,R]) 的答案,实际上可以视作向量之和与 (P) 的叉乘。所以就诞生了一个 (Theta(n^2log n)) 的做法,就是说可以把每个区间对应的点都建出来,可以看出答案一定在凸壳上直接二分即可。

    假设 (T(L,R)) 表示区间 ([L,R]) 表示的点,那么你可以看出 (T(L,R)=T(L,x)+T(x+1,R)),那么你就可以直接分治再用闵可夫斯基和求出凸壳。

    需要注意的是 (x) 正负不同的时候最值不同(一个求最小,一个求最大),所以需要存两个,复杂度是 (Theta(nlog^2n+mlog n))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define int long long
    #define MAXN 200005
    
    template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
    template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
    template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    template <typename T> void chkmax (T &a,T b){a = max (a,b);}
    template <typename T> void chkmin (T &a,T b){a = min (a,b);}
    
    int n,m,mn,mx,sv1,sv2;
    struct Vector{
    	int x,y;
    	int operator * (const Vector &p)const{return x * p.y - y * p.x;}
    	Vector operator + (const Vector &p)const{return Vector {x + p.x,y + p.y};}
    	Vector operator - (const Vector &p)const{return Vector {x - p.x,y - p.y};}
    	bool operator < (const Vector &p)const{return x != p.x ? x < p.x : y < p.y;}
    }A[MAXN];
    
    int tp1,tp2,siz[2];
    Vector p[MAXN],st1[MAXN],st2[MAXN],pnt[2][MAXN];
    
    double Slope (Vector A){
    	return (double)A.y * 1.0 / A.x;
    }
    
    void Convex (Vector *sta,int &top,Vector *p,int len){
    	top = 0,sort (p + 1,p + len + 1);
    	for (Int i = 1;i <= len;++ i){
    		if (top && sta[top].x == p[i].x) -- top;
    		while (top > 1 && Slope(p[i] - sta[top - 1]) > Slope(sta[top] - sta[top - 1])) -- top;
    		sta[++ top] = p[i];
    	}
    }
    
    void Conv (Vector *Sta,int &top,int l,int r,int xs){
    	int len = 0;
    	for (Int i = l;i <= r;++ i) p[++ len] = Vector{A[i].x * xs,A[i].y * xs};
    	Convex (Sta,top,p,len);
    }
    
    void Solveit (int l,int r){
    	if (l == r) return ;
    	int mid = (l + r) >> 1;
    	Solveit (l,mid),Solveit (mid + 1,r);
    	for (Int k = 0;k < 2;++ k){
    		Conv (st1,tp1,mid + 1,r,k ? -1 : 1),Conv (st2,tp2,l,mid,k ? 1 : -1);
    		int vx = st1[1].x + st2[1].x,vy = st1[1].y + st2[1].y,t = 0;
    		for (Int i = 1;i < tp1;++ i) p[++ t] = st1[i + 1] - st1[i];
    		for (Int i = 1;i < tp2;++ i) p[++ t] = st2[i + 1] - st2[i];
    		sort (p + 1,p + t + 1,[](Vector x,Vector y){return Slope (x) > Slope(y);});
    		pnt[k][++ siz[k]] = Vector{vx,vy};
    		for (Int i = 1;i <= t;++ i) vx += p[i].x,vy += p[i].y,pnt[k][++ siz[k]] = Vector{vx,vy};
    	}
    }
    
    signed main(){
    	freopen ("area.in","r",stdin);
    	freopen ("area.out","w",stdout);
    	read (n,m);
    	for (Int i = 1;i <= n;++ i){
    		read (A[i].x,A[i].y),A[i] = A[i - 1] + A[i];
    		chkmin (sv1,A[i].x - mx),chkmax (mx,A[i].x),chkmax (sv2,A[i].x - mn),chkmin (mn,A[i].x);
    	}
    	Solveit (0,n),Convex (pnt[0],siz[0],pnt[0],siz[0]),Convex (pnt[1],siz[1],pnt[1],siz[1]);
    	while (m --> 0){
    		int x,y;read (x,y);
    		if (x == 0) write (max (-sv1 * y,-sv2 * y)),putchar ('
    ');
    		else{
    			int k = x < 0,ans = 0,l = 1,r = siz[k];
    			if (x < 0) x *= -1,y *= -1;Vector P = Vector{x,y};
    			while (l < r){
    				int mid1 = (l + r) >> 1,mid2 = mid1 + 1;
    				int v1 = P * pnt[k][mid1],v2 = P * pnt[k][mid2];
    				if (v1 > v2) chkmax (ans,v1),r = mid1;
    				else chkmax (ans,v2),l = mid2;
    			}
    			write (ans),putchar ('
    ');
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    作业要求 20201022-1 每周例行报告
    作业要求 20201015-3 每周例行报告
    20201008-1 每周例行报告
    20200924-1 每周例行报告
    总结
    20201126-1 每周例行报告
    20201120-1 每周例行报告
    20201112-1 每周例行报告
    20201105-1 每周例行报告
    20201029-1 每周例行报告
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/14932280.html
Copyright © 2011-2022 走看看