zoukankan      html  css  js  c++  java
  • [NOIP模拟赛] 2021.11.16

    T1

    对所有长度大于等于3的子区间计算长高成山峰的花费和,一个区间长高成山峰的花费等于每个数字增大的花费和。

    DDG的牛逼单调栈,危黑灵永远游荡在我们周围!

    枚举的是山峰,算贡献只算到这个山峰的。

    极短代码
    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 1000005;
    const int MOD = 1e9+7;
    int n,ans;
    int a[MAXN];
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int s[MAXN],tl;
    
    int main()
    {
    //	freopen("mountain.in","r",stdin);
    //	freopen("mountain.out","w",stdout);
    	n = Read();
    	for(int i = 1;i <= n;++ i) a[i] = Read();
    	for(int i = 1;i <= n;++ i)
    	{
    		while(tl && a[i] >= a[s[tl]])
    		{
    			if(tl > 1) ans = (ans + (n-i+1ll) * (Min(a[i],a[s[tl-1]])-a[s[tl]]) % MOD * (i-s[tl-1]-1) % MOD * s[tl-1] % MOD) % MOD;
    			--tl; 
    		}
    		s[++tl] = i;
    	}
    	Put(ans,'\n');
    	return 0;
    }
    //426406027
    
    

    T2

    赛时切了,是个比较简单的背包。

    赛时代码
    //12252024832524
    #include <bits/stdc++.h>
    #define TT template<typename T>
    using namespace std;
    
    typedef long long LL;
    const int MAXN = 55;
    const int MAXA = 505;
    const int B = 51*500;
    const int C = 500;
    int n,m,ans;
    int a[MAXN][MAXN];
    int dp[2][B<<1|5],r[MAXN][MAXA<<1],c[MAXN][MAXA<<1];
    
    LL Read()
    {
    	LL x = 0,f = 1; char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int main()
    {
    	freopen("matrix.in","r",stdin);
    	freopen("matrix.out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = 0;i < n;++ i)
    		for(int j = 0;j < m;++ j) 
    			a[i][j] = Read();
    	for(int i = 0;i < n;++ i)
    		for(int j = 0;j < m;++ j)
    		{
    			int to = (i-1+n)%n;
    			++r[i][a[i][j]-a[to][j]+C];
    		}
    	for(int i = 0;i < n;++ i)
    		for(int j = 0;j < m;++ j)
    		{
    			int to = (j-1+m)%m;
    			++c[j][a[i][j]-a[i][to]+C];
    		}
    	int L = B,R = B;
    	for(int i = 1;i < n;++ i)
    	{
    		bool now = i&1,to=now^1;
    		memset(dp[now],0,sizeof(dp[now]));
    		int M = 0;
    		for(int j = L;j <= R;++ j) M = Max(M,dp[to][j]);
    		for(int j = L;j <= R;++ j)
    		{
    			for(int kk = 0,k;kk < m;++ kk)
    			{
    				k = a[i][kk] - a[i-1][kk];
    				dp[now][j+k] = Max(dp[now][j+k],dp[to][j]+r[i][k+C]);
    			}
    		}
    		L -= 500; R += 500;
    		for(int j = L;j <= R;++ j) dp[now][j] = Max(dp[now][j],M);
    	}
    	int val = 0;
    	for(int i = L;i <= R;++ i) val = Max(val,dp[(n-1)&1][i]+((C-(i-B) >= 0 && C-(i-B) <= 1000) ? r[0][C-(i-B)] : 0));
    	ans += val;
    	//---
    	L = B,R = B;
    	memset(dp[0],0,sizeof(dp[0]));
    	for(int i = 1;i < m;++ i)
    	{
    		bool now = i&1,to=now^1;
    		memset(dp[now],0,sizeof(dp[now]));
    		int M = 0;
    		for(int j = L;j <= R;++ j) M = Max(M,dp[to][j]);
    		for(int j = L;j <= R;++ j)
    		{
    			for(int kk = 0,k;kk < n;++ kk)
    			{
    				k = a[kk][i] - a[kk][i-1];
    				dp[now][j+k] = Max(dp[now][j+k],dp[to][j]+c[i][k+C]);
    			}
    		}
    		L -= 500; R += 500;
    		for(int j = L;j <= R;++ j) dp[now][j] = Max(dp[now][j],M);
    	}
    	val = 0;
    	for(int i = L;i <= R;++ i) val = Max(val,dp[(m-1)&1][i]+((C-(i-B) >= 0 && C-(i-B) <= 1000) ? c[0][C-(i-B)] : 0));
    	ans += val;
    	Put(ans,'\n');
    	return 0;
    }
    /*
    可以考虑 ri-1 和 ri 满足什么关系可以获得贡献
    地球是个环,所以还是有关的,但是可以dp
    这负数真的恶心至极 
    */
    

    T3

    \/ 不要正方形构造题。

    考虑翻转调整字典序必定变小,所以直接费用流。

    只需从左上到右下定义费用逐渐增大即可,因为费用流优先增广费用小的。

    还可以暴力调整,但是复杂度劣一些。

    T4

    给定一些字符必须转换,可以多次进行,求最大保留字符种类。

    差两点。

    一点是没相当转化成匹配问题,一点是题面出锅打一半就觉得完全不可做。

    其实就是字符去填空,缩点之后变成很多强连通分量。

    一些是需要转化的,一些是可以内部消耗边的(有空的)。

    需要转化的连向可以转到的点(可以也是需要转化的点),最大匹配就是可以保留的最多的字符种类。

    注意一些本来就没有的字符不要算到贡献里面。

  • 相关阅读:
    canvas gamebricks
    javascript 判断对象的值是否相等
    让控件全屏显示(WinForm)
    网络视频监控
    回调函数
    [导入][链接]FreeBSD + Sun Java
    [导入][一点一滴学英语]20060330
    [导入][来自网络] 酸酸甜甜就是我 不用我多介绍了 可是你是否听过天津话的版本?
    [导入][链接]差点漏掉 Eclipse 3.2 M6出来了
    [导入][链接]Five reasons why you should never use PostgreSQL
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15561989.html
Copyright © 2011-2022 走看看