zoukankan      html  css  js  c++  java
  • 2021省选

    D1 T1 卡牌游戏

     

    将2n个值(每张卡牌的AB面)混在一起从小到大排序并记录每一个值是A面还是B面

    排序后答案显然是其中一段子序列的两端之差

    这里以样例举例:

    这样问题就转化为给2n个数要删除前面一段、后面一段,要求:

    • 删除的A面总数不能超过要求

    • 不能同时删除同一张卡的两面

    对于第一条用一个变量动态实时记录即可

    对于第二条用一个桶维护就可以完美解决了

    空间复杂度:O(n)

    时间复杂度:O(nlogn)   瓶颈在排序

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define N 1000005
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*f;
    }
    struct arr{
    	int x,id,op;
    }a[N<<1];
    int n,k;
    inline bool cmp(arr A,arr B){return A.x<B.x;}
    bool vis[N];
    int main()
    {
    	n=read();k=read();
    	for(int i=1;i<=n;i++) a[i].x=read(),a[i].id=i,a[i].op=1;
    	for(int i=1;i<=n;i++) a[i+n].x=read(),a[i+n].id=i;
    	sort(a+1,a+(n<<1)+1,cmp);
    	int l=0,r=(n<<1)+1,now=0,ans=2e9;
    	while(!vis[a[r-1].id] && now+a[r-1].op<=k) vis[a[--r].id]=1,now+=a[r].op;
    	while(!vis[a[l+1].id] && now+a[l+1].op<=k) vis[a[++l].id]=1,now+=a[l].op;
    	while(r<(n<<1))
    	{
    		ans=min(ans,a[r-1].x-a[l+1].x);
    		vis[a[++r].id]=0;
    		now-=a[r].op;
    		while(!vis[a[l-1].id] && now+a[l-1].op<=k) vis[a[--l].id]=1,now+=a[l].op;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    D1 T2 矩阵游戏

    看到题面后注意到难点在于要控制构造出的原矩阵中每一个位置的数的值在0~1e6之间

    那么先考虑没有这条限制的情况下如何构造出原矩阵

    因为没有了限制不难发现我们只要钦定 ai,1=a1,j=0就可以生成一个唯一的矩阵a' (a'[i][j]=b[i][j]-a'[i+1][j]-a'[i][j+1]-a'[i+1][j+1])

    我们再考虑通过调整某些位置的权值使得最后的解满足限制

    手玩样例和推式子后我们可以发现:

    1、对于某一行我们交替进行+r、-r、+r、-r……后的解仍然满足给定的矩阵b的限制

    2、对于某一列我们交替进行+c、-c、+c、-c……后的解也仍然满足给定的矩阵b的限制

    于是任意一组解都可以被我们表示为:

    现在考虑0<=ai,j<=1e6这条限制,我们可以将r序列与c序列作为未知量进行差分约束

    但是此时的差分约束的式子长成这样(设Ai,j为a‘i,j的“增量”,即ri与ci对a‘i,j的贡献):-ai,j<=Ai,j<=1e6-ai,j

    由于Ai,j的形式不好看并不好进行差分约束(也不是不能,但好像超级麻烦)(差分约束的一般式子形式如:x<=y+val)

    所以我们可以对奇数列的c序列取反,偶数行的r序列取反使得“奇列偶行”取反后的Ai,j的形式形如x-y

    然后我们就可以得到一个很优美的矩阵:

    然后就可以愉快的差分约束了(注意要开long long

    空间复杂度:O(n2)

    最坏时间复杂度:O(n3) (本人加了双端队列优化所以时间复杂度在随机数据下会快亿一点,但可能也会被毒瘤数据卡歇逼)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<deque>
    #define N 605
    #define pb push_back
    #define mp make_pair
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*f;
    }
    int n,m,a[N][N],b[N][N];
    vector<pair<int,int> > v[N];
    deque<int> q;
    bool vis[N];
    int sum[N];
    long long dis[N];
    inline void clear()
    {
    	for(int i=1;i<=n+m;i++) v[i].clear();
    	while(!q.empty()) q.pop_front();
    	memset(b,0,sizeof(b));
    	memset(vis,0,sizeof(vis));
    	memset(sum,0,sizeof(sum));
    	memset(dis,999999,sizeof(dis));
    }
    int main()
    {
    	int T=read();
    	while(T--)
    	{
    		clear();
    		n=read();m=read();
    		for(int i=1;i<n;i++)
    		    for(int j=1;j<m;j++)
    		        a[i][j]=read();
    		for(int i=n-1;i>=1;i--)
    		    for(int j=m-1;j>=1;j--)
    		        b[i][j]=a[i][j]-b[i+1][j]-b[i][j+1]-b[i+1][j+1];
    		for(int i=1;i<=n;i++)
    		    for(int j=1;j<=m;j++)
    		    {
    		    	int mx=1e6-b[i][j],mn=-b[i][j];
    		    	if((i+j)&1) v[j+n].pb(mp(i,-mn)),v[i].pb(mp(j+n,mx));
    		    	else v[j+n].pb(mp(i,mx)),v[i].pb(mp(j+n,-mn));
    			}
    		for(int i=1;i<=n+m;i++) v[0].pb(mp(i,0));
    		q.push_front(0);
    		dis[0]=0;
    		bool flag=1;
    		while(!q.empty())
    		{
    			int x=q.front();q.pop_front();
    			++sum[x];vis[x]=0;
    			if(sum[x]>n+m){flag=0;printf("NO
    ");break;}
    			for(int i=0;i<v[x].size();i++)
    			    if(dis[v[x][i].first]>dis[x]+v[x][i].second)
    			    {
    			    	dis[v[x][i].first]=dis[x]+v[x][i].second;
    			    	if(!vis[v[x][i].first])
    			    	{
    			    		if(!q.empty() && dis[v[x][i].first]<dis[q.front()]) q.push_front(v[x][i].first);
    			    		else q.push_back(v[x][i].first);
    			    		vis[v[x][i].first]=1;
    					}
    				}
    		}
    		if(!flag) continue;
    		for(int i=1;i<=n;i++)
    		    for(int j=1;j<=m;j++)
    		    {
    		    	if((i+j)&1) b[i][j]-=dis[i];
    		    	else b[i][j]+=dis[i];
    		    	if((i+j)&1) b[i][j]+=dis[j+n];
    		    	else b[i][j]-=dis[j+n];
    			}
    		printf("YES
    ");
    		for(int i=1;i<=n;i++)
    		{
    		    for(int j=1;j<=m;j++) printf("%d ",b[i][j]);
    			puts("");
    		}
    	}
    	return 0;
    }
    

    后续正在更新ing……

  • 相关阅读:
    MVC上传文件并模拟进度条
    C#文件的压缩和解压(ZIP)使用DotNetZip封装类操作zip文件(创建/读取/更新)实例
    Inherits、CodeFile、CodeBehind的区别
    .csproj文件的配置 IIS可以调试
    C# <%@ Register %>指令
    将n行3列的数据dataTable装换成m行7列的dataTable
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: 命名管道提供程序, error: 40
    Js全选,插入实现
    Jquery autocomplete插件的使用
    jquery.autocomplete自动补全功能
  • 原文地址:https://www.cnblogs.com/chenjiaxuan/p/14686388.html
Copyright © 2011-2022 走看看