zoukankan      html  css  js  c++  java
  • noip多校模拟23

    考试过程:开考先看题,觉得按顺序开题比较合适。首先是T1,刚开始没什么思路,而且比较困,神游了半个小时。然后突然有了思路,想到了回文串必定会有一个对称中心,那么我们可以从这个中心出发向两边扩展,设当前矩形的左上角和右下角分别是(x1,y1,x2,y2),那么可以扩展到
    (x1-1,y1,x2+1,y2)
    (x1-1,y1,x2,y2+1)
    (x1,y1-1,x2+1,y2)
    (x1,y1-1,x2,y2+1)
    四个方向的矩形,直接转移即可,这样的复杂度是(o(n^4)),可以获得(50pts),然后我想了一会,觉得应该可以用类似与步数的方式优化到(o(n^3)),但是没什么具体的思路,就先打后面的题。
    T2,阅读程序题,指针满天飞,属实看不懂,就弃掉了。
    T3,想了一会想到一个(dp)思路,可以拿到(44pts),但是考场上打挂了,只拿了(12pts),错了好多小点,所以以后一定要测试点分治。
    T4,没什么时间想了,就按照题意模拟,拿了(42pts)
    总结:1.一定要打测试点分治
    2.在看不懂题的情况下不要放弃,可以先看特殊性质,拿到白送的分。
    3.如果有优化的思路,就要留出时间思考。

    T1 回文

    思路:暴力思路上面已经说过了,现在考虑如何优化。从对称中心出发,那么到达((1,1))((n,m))的步数是一样的,所以一定满足这样的柿子(x1=n-x2+1,y1=m-y2+1),那么一定满足(x1+y1+x2+y2==n+m+2),那么如果我们知道了(x1,y1,x2),那么(y2),可以通过计算得知,这样的复杂度就降到了(o(n^3))
    所以我们设(f_{i,j,k})表示枚举的矩形的左上角为((i,j)),右下角的横坐标为(k)的方案数。转移是显然的。
    最后考虑如何统计答案,我们找到所有(x+y-1==((n+m-2)/2)+1)的点,那么只需要(ans+=f_{x,y,x+1}+f_{x,y,x})即可。
    代码如下:

    AC_code
    
    #include<bits/stdc++.h>
    #define re register int
    #define ii inline int
    #define iv inline void
    using namespace std;
    const int mo=993244853;
    const int N=505;
    int f[N][N][N];
    char s[510][510];
    int n,m,ans;
    ii read()
    {
    	int x=0; char ch=getchar(); bool f=1;
    	while(ch<'0' or ch>'9')
    	{
    		if(ch=='-') f=0;
    		ch=getchar();
    	}
    	while(ch>='0' and ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    iv add(int &x,int y)
    {
    	x=x+y;
    	if(x>=mo) x-=mo;
    }
    int main()
    {
    	freopen("palin.in","r",stdin);
    	freopen("palin.out","w",stdout);
    	n=read(),m=read();
    	for(re i=1;i<=n;i++)
    	{
    		scanf("%s",s[i]+1);
    	}
    	if(s[1][1]!=s[n][m]) {printf("0
    ");return 0;}
    	f[1][1][n]=1;
    	for(re i=1;i<=n;i++)
    	{
    		for(re j=1;j<=m;j++)
    		{
    			for(re k=n;k>=i;k--)
    			{
    				int p=n+m-i-j-k+2;
    				if(i==k and j==p) continue;
    				if(p<j) continue;
    				if((k-1>=i and j+1<=p) and s[i][j+1]==s[k-1][p]) add(f[i][j+1][k-1],f[i][j][k]);
    				if((p-1>=j+1) and s[i][j+1]==s[k][p-1]) add(f[i][j+1][k],f[i][j][k]);
    				if((k-1>=i+1) and s[i+1][j]==s[k-1][p]) add(f[i+1][j][k-1],f[i][j][k]);
    				if((i+1<=k and p-1>=j)  and s[i+1][j]==s[k][p-1]) add(f[i+1][j][k],f[i][j][k]);
    			}
    		}
    	}
    	int len=(n+m-2)>>1;
    	for(re i=1;i<=n;i++)
    	{
    		for(re j=1;j<=m;j++)
    		{
    			if((i+j-1)==len+1)
    			{
    				add(ans,f[i][j][i+1]);
    				add(ans,f[i][j][i]);
    			}
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
    

    T2 快速排序

    思路:经过计算机带师ICEY的讲解,终于看懂了题意。
    首先,如果所有被排序数都非 nan,那么必然是按升序排列。
    否则,我们考虑第一个数 (x)
    如果 (x)(nan),那相当于把一个 (nan) 置于最前,然后排序其余的数。
    否则,相当于把所有剩下的 (< x) 的数从小到大放在 (x) 之前,并放置 (x)
    那么这个过程可以使用优先队列来实现。代码如下:

    AC_code
    
    #include<bits/stdc++.h>
    #define re register int
    #define ii inline int
    #define iv inline void
    using namespace std;
    const int N=5e5+10;
    struct node
    {
    	bool is;
    	int val;
    }cun[N];
    int t,n,cnt;
    priority_queue<int,vector<int>,greater<int> >Q;
    ii read()
    {
    	int x=0; char ch=getchar(); bool f=1;
    	while(ch<'0' or ch>'9')
    	{
    		if(ch=='n')
    		{
    			f=0;
    			ch=getchar();
    			ch=getchar();
    			ch=getchar();
    			return -1;
    		}
    		ch=getchar();
    	}
    	while(ch>='0' and ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-1);
    }
    int main()
    {
    	freopen("qsort.in","r",stdin);
    	freopen("qsort.out","w",stdout);
    	t=read();
    	while(t--)
    	{
    		n=read();
    		for(re i=1;i<=n+1;i++) cun[i]=(node){0,0};
    		for(re i=1;i<=n;i++)
    		{
    			int x=read();
    			if(x==-1) cun[i].is=1;
    			else {cun[i].val=x,Q.push(x);}
    		}
    		for(re i=1;i<=n;++i)
    		{
    			if(cun[i].is==1) printf("nan ");
    			else
    			{
    				while(Q.size() and Q.top()<cun[i].val) printf("%d ",Q.top()),Q.pop();
    				if(Q.size() and Q.top()==cun[i].val) printf("%d ",Q.top()),Q.pop();
    			}
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
    
    

    T3 混乱邪恶

    思路:目前只会打部分分,说一下部分分的思路:我们设(f_{i,j0/1})表示前(i)个数能否凑出和为(j),如果可以,那么最后一个数的位置是什么。那么我们就可以暴力转移了。考虑优化,我们显然可以滚掉一维,但是要注意,如果之前已经凑出过当前位置的数了,那么就不需要更新了,否则因为我利用的是之前的数进行的更新,当我修改之后,当我统计答案的时候就不对了。
    代码如下:

    AC_code
    
    #include<bits/stdc++.h>
    #define re register int
    #define ii inline int
    #define iv inline void
    using namespace std;
    const int N=1e6+10;
    int n,m,sum;
    int a[N],ans[N];
    int f[N][2],pre[N][2];
    bool flag;
    ii read()
    {
    	int x=0; char ch=getchar(); bool f=1;
    	while(ch<'0' or ch>'9')
    	{
    		if(ch=='-') f=0;
    		ch=getchar();
    	}
    	while(ch>='0' and ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    signed main()
    {
    	freopen("chaoticevil.in","r",stdin);
    	freopen("chaoticevil.out","w",stdout);
    	n=read(),m=read();
    	for(re i=1;i<=n;i++) a[i]=read(),sum+=a[i];
    	sum/=2;
    	for(re i=1;i<=n;i++) ans[i]=-1;
    	f[a[1]][0]=f[a[1]][1]=1;
    	for(re i=2;i<=n;i++)
    	{
    		for(re j=sum-a[i];j;j--)
    		{
    			if( (!f[j+a[i]][0]) and (f[j][0]) )
    			{
    				f[j+a[i]][0]=1;
    				f[j+a[i]][1]=i;
    				pre[j+a[i]][0]=f[j][1];	
    				pre[j+a[i]][1]=j;
    			}
    		}
    		if(!f[a[i]][0])
    		{
    			f[a[i]][0]=1,f[a[i]][1]=i;
    			pre[a[i]][0]=pre[a[i]][1]=0;
    		}
    		if(f[sum][0]) {flag=1;break;}
    	}
    	if(flag)
    	{
    		printf("NP-Hard solved
    ");
    		ans[f[sum][1]]=1;
    		while(sum and pre[sum][0])
    		{
    			ans[pre[sum][0]]=1;
    			sum=pre[sum][1];
    		}
    		for(re i=1;i<=n;i++)
    			printf("%d ",ans[i]);
    		printf("
    ");
    	}
    	else printf("Chaotic evil
    ");
    	return 0;
    }
    
    
    

    T4 校门外歪脖树上的鸽子

    咕了。

  • 相关阅读:
    Array.sort()对象数组排序
    ES6极简数组去重 & 深拷贝
    中文字符按拼音首字母排序(转)
    浏览器常用插件 & 开发常用类库
    异步&分段处理海量数据
    线上环境window.open()新窗口被拦截(转)
    git 版本回退(转)
    CSS字体渐变 & 隐藏浏览器滚动条 & grid布局(转载)
    Python3安装使用SaltStack以及salt-api详解
    Python3之 contextlib
  • 原文地址:https://www.cnblogs.com/WindZR/p/15515287.html
Copyright © 2011-2022 走看看