11.08练习赛

11.08练习赛

T1 吃糖

这道题没有什么好说的,从100枚举到2,用\(N^2\)的搜索暴力\(Check\)即可。

然而我打爆了

最后发现是在dfs2里条件判断错误。

我真是个憨憨

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
char *p1,*p2,buf[1<<20];
//#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++)))
#define GC getchar()
#define ri register int
inline int in()
{
	int w=0,x=0;
	char ch=0;
	while(!isdigit(ch)){
		w|=ch=='-';
		ch=GC;
	}
	while(isdigit(ch)){
		x=(x<<3)+(x<<1)+(ch^48);
		ch=GC;
	}
	return w? -x:x;
}
int r,c;
int a[110][110];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int _max;
int cut=0;
struct point{
	int x,y;
};
queue<point>q;
bool vis[110][110];
bool vis1[110][110];
void dfs(int x,int y,int k)
{
	vis[x][y]=1;
	cut+=1;
	int i;
	for(i=0;i<4;i++){
		int tx=x+dx[i],ty=y+dy[i];
		if(vis[tx][ty])continue;
		if(tx==0||tx==r+1||ty==0||ty==c+1)continue;
		if(a[tx][ty]<k)continue;
		dfs(tx,ty,k);
	}
	return;
}
int dfs1(int x,int y)
{
	vis1[x][y]=1;
	int i;
	int k=1;
	for(i=0;i<4;i++){
		int tx=x+dx[i],ty=y+dy[i];
		if(vis[tx][ty])continue;
		if(vis1[tx][ty])continue;
		if(tx==0||tx==r+1||ty==0||ty==c+1)continue;
		k+=dfs1(tx,ty);
	}
	return k;
}
bool check(int x)
{
	memset(vis,0,sizeof(vis));
	memset(vis1,0,sizeof(vis1));
	int i,j;
	cut=0;
	for(i=1;i<=c;i++){
		if(a[1][i]>=x)q.push((point){1,i});
		if(a[r][i]>=x)q.push((point){r,i});
	}
	for(i=1;i<=r;i++){
		if(a[i][1]>=x)q.push((point){i,1});
		if(a[i][c]>=x)q.push((point){i,c});
	}
	while(q.size()){
		int A=q.front().x,B=q.front().y;
		q.pop();
		if(vis[A][B])continue;
		dfs(A,B,x);
	}
	for(i=1;i<=r;i++)
	{
		for(j=1;j<=c;j++)
		{
			if(!vis[i][j]){
				int k=dfs1(i,j);
				if(k==r*c-cut){
					return 0;
				}
				else return 1;
			}
		}
	}
	return 0;
}
bool inf[110];
int main()
{
//	freopen("candies.in","r",stdin);
//	freopen("candies.out","w",stdout);
	r=in();c=in();
	ri i,j;
	for(i=1;i<=r;i++)
	{
		for(j=1;j<=c;j++)
		{
			a[i][j]=in();
			inf[a[i][j]]=1;
			_max=max(_max,a[i][j]);
		}
	}
	for(i=_max;i>=2;i--)
	{
		if(check(i)){
			printf("%d\n",i);
			return 0;
		}
	}
	printf("-1\n");	
	return 0;
}

T2 卡片

题面是真的长,而且大部分都没用

稍微描述一下题面:

其实就是一个三关键字排序,问最多能选出多少个连续的数集。

听liudl带佬说是三维偏序,于是我打了个二位数点(逃

首先膜一下Qhr带佬,他居然是(本人所知)全小机房唯一一个想出来可以用图论来搞这道题人。而这也是本题的正解(之一)。能拿20那种

(具体做法是把所有\(p_i<p_j\)的点连起来,然后跑最长路)

正解是用一个叫做CDQ分治的东西把三维转换成二维。然而我并不会

还有一个正解就是把20分做法和80分做法整合起来,就能A掉了。

注:在这种小规模的最短/长路中最好用SPFA,又短又好写而且小数据绝对卡不掉。(关于SPFA:他活了)

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
char *p1,*p2,buf[1<<20];
//#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++)))
#define GC getchar()
inline int in() {
	int x=0,w=0;
	char ch=0;
	while(!isdigit(ch)) {
		w|=ch=='-';
		ch=GC;
	}
	while(isdigit(ch)) {
		x=(x<<3)+(x<<1)+(ch^48);
		ch=GC;
	}
	return w? -x:x;
}
inline int lowbit(int x) {
	return x&(-x);
}
const int maxn= 1e6 + 5;
struct node {
	int x,y,z;
} g[maxn];
int _max;
int n;
namespace s1 {
	bool cmp(node a,node b) {
		if(a.x!=b.x)return a.x<b.x;
		else return a.y<b.y;
	}
	int sum[1000010];
	void ins(int x,int k) {

		for(; x<=maxn; x+=lowbit(x)) {
			sum[x]=max(sum[x],k);
			if(x==0)break;
		}
		return;
	}
	int gs(int x) {
		int res=0;
		for(;;x-=lowbit(x)) {
			res=max(res,sum[x]);
			if(x==0)break;
		}
		return res;
	}
	void s1() {
		sort(g+1,g+n+1,cmp);
		int ans=0;
		for(int i=1; i<=n; ++i) {
			int v=g[i].y;
			ins(v,gs(v)+1);
			ans=max(ans,gs(v));
		}
		printf("%d\n",ans);
		return;
	}
}
namespace s2 {
	struct edge {
		int to,next;
	} e[maxn*2];
	int head[maxn],cnt;
	void add(int from,int to) {
		e[++cnt].next=head[from];
		e[cnt].to=to;
		head[from]=cnt;
	}
	int ans=0;
	bool inq[maxn];
	int dis[maxn];
	queue<int>q;
	void spfa(int x)
	{
		for(int i=1;i<=n;i++)dis[i]=inq[i]=0;
		q.push(x);
		inq[x]=1;
		while(q.size()){
			int u=q.front();
			q.pop();
			inq[u]=0;
			for(int i=head[u];i;i=e[i].next){
				int v=e[i].to;
				if(dis[u]+1>dis[v]){
					dis[v]=dis[u]+1;
					if(!inq[v]){
						q.push(v);
						inq[v]=1;
					}
				}
			}
		}
	}
	void s2() {
		int i,j;
		for(i=1; i<=n; i++) {
			for(j=1; j<=n; j++) {
				if(i==j)continue;
				if(g[i].x<=g[j].x&&g[i].y<=g[j].y&&g[i].z<=g[j].z){
					add(i,j);
				}
			}
		}
		for(i=1; i<=n; i++) {
			spfa(i);
			for(j=1;j<=n;j++)
			{
				ans=max(ans,dis[j]+1);
			}
		}
		printf("%d\n",ans);
		return;
	}
}
int main() {
	bool if0=1;
	n=in();
	for(int i=1; i<=n; ++i) {
		g[i].x=in();
		g[i].y=in();
		g[i].z=in();
		if(g[i].z!=0)if0=0;
		_max=max(g[i].y,_max);
	}
	if(if0) {
		s1::s1();
		return 0;
	} else {
		s2::s2();
		return 0;
	}
}

这次想装一下B所以用了用namespace,好孩子不要学

posted @ 2019-11-10 01:46  国土战略局特工  阅读(114)  评论(0)    收藏  举报