Yali training 2017day2 scribble

t1

First wrote a violent practice: discretize the height, then set \ (f [i] [j] \) to the first \ (i \) position, and the water level is the maximum condition that can be satisfied by \ (j \)

If \ (J \ Le H (i-1, i) \) , it can be from less than \ (h (i-1, i) \) anywhere transferred from

If \ (J> H (. 1-I, I) \) , then the \ (f [i] [j ] \) only from \ (f [i-1] [j] \) Transfer

Engage in a prefix maximum, complexity \ (O (n ^ 2) \)

The positive solution is very fairy, we can traverse the key nodes (conditions and the position of the partition) from the bottom up according to the height

It can be found that in the process of increasing height, some positions will be merged into a whole (water level exceeds the partition), this process can be used and collected for maintenance

Enumerate the height \ (h \) , set two arrays \ (ans, sum \)

Where \ (sum [x] \) means that when the water level height of the Unicom block where \ (x \) is located is \ (h \) , the number of conditions that can be satisfied is not considered, regardless of the conditions above \ (h \)

\ (ans [x] \) means that when the water level height of the connected block where \ (x \) is located does not exceed \ (h \) , the conditions above $ h & are not considered, and the maximum number of conditions can be met

For the same height of information, we first deal with the partition, then deal with the conditions without water, and finally deal with the conditions with water

If the current information is the condition with water: then as long as \ (++ sum [x] \) , also update \ (ans [x] \)

If the current information is a condition without water: then as long as \ (++ ans [x] \) , because the original \ (ans [x] \) is the information below the water level, this condition must be selected.

If it is a partition, merge the \ (ans \) and \ (sum \) of the communication blocks on both sides of the partition

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define y1 qwq 
	inline int read()
	{
		int x=0;char ch,f=1;
		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
		if(ch=='-') f=0,ch=getchar();
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
		return f?x:-x;
	} 
	const int N=1e5+10,inf=1<<30;
	int haku,n,m;
	struct node
	{
		int x,y,z;
		inline bool operator < (const node &t) const
		{
			return y==t.y?z<t.z:y<t.y;
		}
	}a[N<<1];
	int f[N],ans[N],sum[N];
	inline int find(int k)
	{
		return f[k]==k?k:f[k]=find(f[k]);
	}
	inline void main()
	{
		haku=read();
		while(haku--)
		{
			n=read(),m=read();
			memset(ans,0,sizeof(ans));
			memset(sum,0,sizeof(sum));
			for(int i=1;i<n;++i) a[i].x=i,a[i].y=read(),a[i].z=-1;
			for(int i=1;i<=m;++i) a[i+n-1].x=read(),a[i+n-1].y=read(),a[i+n-1].z=read();
			for(int i=1;i<=n;++i) f[i]=i;
			sort(a+1,a+n+m);
			for(int i=1;i<n+m;++i)
			{
				if(a[i].z==-1)
				{
					int x=find(a[i].x),y=find(a[i].x+1);
					if(x==y) continue;
					f[x]=y;ans[y]+=ans[x];sum[y]+=sum[x];
				}
				if(a[i].z==0)
				{
					int x=find(a[i].x);
					++ans[x];
				}
				if(a[i].z==1)
				{
					int x=find(a[i].x);
					ans[x]=max(ans[x],++sum[x]);
				}
			}
			printf("%d\n",ans[find(1)]);
		}
	}
}
signed main()
{
	red::main();
	return 0;
}

t2

This kind of problem and data range is easy to think of a bunch of things like bipartite graph and network flow. .

Consider dropping a pawn. If the Unicom block where the pawn is located is a perfectly matched bipartite graph, then obviously \ (Bob \) can make itself undefeated by walking the matching edge each time

If the position of the piece is not necessarily within the maximum match of the bipartite graph, then \ (Bob \) must enter the edge of the maximum match of the bipartite graph after moving once (and there is no alternate path, because he just walked)

So our task is actually to find all points that do not necessarily exist in the maximum match of the bipartite graph

The specific method is to find all points that are not within the maximum match of the bipartite graph, and then take an alternate path from these points

All left nodes can be selected, because the parts that have passed are replaced by alternate paths from the starting point to the current point, and the parts that have not passed can be unchanged

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define y1 qwq
#define id(x,y) (((x)-1)*m+(y))
	inline int read()
	{
		int x=0;char ch,f=1;
		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
		if(ch=='-') f=0,ch=getchar();
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
		return f?x:-x;
	} 
	const int N=1e5+10,inf=1<<30;
	int n,m;
	char s[110][110]; 
	int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
	int head[N],cnt;
	struct point
	{
		int nxt,to;
		point(){}
		point(const int &nxt,const int &to):nxt(nxt),to(to){}
	}a[N<<1];
	inline void link(int x,int y)
	{
		a[++cnt]=(point){head[x],y};head[x]=cnt;
		a[++cnt]=(point){head[y],x};head[y]=cnt;
	}
	int st[N<<1],top;
	int f[N<<1],vis[N<<1],tim;
	bool ans[N<<1];
	inline bool find(int now)
	{
		for(int i=head[now];i;i=a[i].nxt)
		{
			int t=a[i].to;
			if(vis[t]==tim) continue;
			vis[t]=tim;
			if(!f[t]||find(f[t]))
			{
				f[t]=now;
				return 1;
			}
		}
		return 0;
	}
	inline void dfs(int now)
	{
		ans[now]=1;
		for(int i=head[now];i;i=a[i].nxt)
		{
			int t=a[i].to;
			if(f[t]&&!ans[f[t]]) dfs(f[t]);
		}
	}
	inline void main()
	{
		n=read(),m=read();
		for(int i=1;i<=n;++i) scanf("%s",s[i]+1);
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=m;++j)
			{
				if(s[i][j]=='.')
				{
					for(int k=0;k<4;++k)
					{
						int tx=i+dx[k],ty=j+dy[k];
						if(s[tx][ty]!='.') continue;
						link(id(i,j),id(tx,ty)+n*m);
						link(id(tx,ty)+n*m,id(i,j)); 
					}
				}
			}
		}
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=m;++j)
			{
				if(s[i][j]=='.')
				{
					++tim;
					if(!find(id(i,j))) st[++top]=id(i,j);
				}
			}
		}
		if(!top) return(void)puts("LOSE");
		for(int i=1;i<=top;++i) dfs(st[i]);
		top=0;
		for(int i=1;i<=n*m;++i)
			if(ans[i]) st[++top]=i;
		if(!top) return(void)puts("LOSE");
		puts("WIN");
		for(int i=1;i<=top;i++) printf("%d %d\n",(st[i]-1)/m+1,(st[i]-1)%m+1); 
	}
}
signed main()
{
	red::main();
	return 0;
}

t3

Li Chaoshu template question, adjusted for \ (4 \) hours, my mind exploded and woo woo woo woo

My wording is too ugly, so I wo n’t let it go. Go online and find someone else ’s board QAQ

Guess you like

Origin www.cnblogs.com/knife-rose/p/12741899.html