2.16学习总结

1.邮递员送信(dijkstra 不只是从起到到目标点,还要走回去)
2.炸铁路(并查集)
3.统计方形(数据加强版)(排列组合)
4.滑雪(记忆化)
5.小车问题(数学问题)
6.ACM(记忆化,搜索)
7.奶牛的耳语(二分)
8.计算器的改良(模拟)
9.L-shapes(遍历)
10.Alternating Heights(拓扑排序+二分)

邮递员送信https://www.luogu.com.cn/problem/P1629

题目描述

有一个邮递员要送东西,邮局在节点 11。他总共要送 �−1n−1 样东西,其目的地分别是节点 22 到节点 �n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 �m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 �−1n−1 样东西并且最终回到邮局最少需要的时间。

输入格式

第一行包括两个整数,�n 和 �m,表示城市的节点数量和道路数量。

第二行到第 (�+1)(m+1) 行,每行三个整数,�,�,�u,v,w,表示从 �u 到 �v 有一条通过时间为 �w 的道路。

输出格式

输出仅一行,包含一个整数,为最少需要的时间。

输入输出样例

输入 #1复制

5 10
2 3 5
1 5 5
3 5 6
1 2 8
1 3 8
5 3 4
4 1 8
4 5 3
3 5 6
5 4 2

输出 #1复制

83

说明/提示

对于 30%30% 的数据,1≤�≤2001≤n≤200。

对于 100%100% 的数据,1≤�≤1031≤n≤103,1≤�≤1051≤m≤105,1≤�,�≤�1≤u,v≤n,1≤�≤1041≤w≤104,输入保证任意两点都能互相到达。

思路:与平常最短路不同的是,这个需要走回去,那就把邻接表反过来,在走一遍dijkstra

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N=1005;
int n,m;

struct node{
	int to;
	int w;
	node(int b,int c){
		to=b;
		w=c;
	}
};
vector<node>e1[N];
vector<node>e2[N];
int dis1[N],dis2[N];
struct s_node{
	int id;
	int n_dis;
	s_node(int a,int b){
		id=a;
		n_dis=b;
	}
	bool operator < (const s_node &a )const{
		return n_dis>a.n_dis;
	}
};

void dijkstra1(){
	priority_queue<s_node>q;
	bool done[N];
	for (int i=1;i<=n;++i){
		done[i]=false;
		dis1[i]=INF;
	}
	dis1[1]=0;
	q.push(s_node(1,dis1[1]));
	while (!q.empty()){
		s_node u=q.top(); q.pop();
		if (done[u.id]) continue;
		done[u.id]=true;
		for (int i=0;i<e1[u.id].size();++i){
			node y=e1[u.id][i];
			if (done[y.to]) continue;
			if (dis1[y.to]> u.n_dis+y.w){
				dis1[y.to]=u.n_dis+y.w;
				q.push(s_node(y.to,dis1[y.to])); 
			}
		}
	}
}

void dijkstra2(){
	priority_queue<s_node>q2;
	bool done[N];
	for (int i=1;i<=n;++i){
		done[i]=false;
		dis2[i]=INF;
	}
	dis2[1]=0;
	q2.push(s_node(1,dis2[1]));
	while (!q2.empty()){
		s_node u=q2.top(); q2.pop();
		if (done[u.id]) continue;
		done[u.id]=true;
		for (int i=0;i<e2[u.id].size();++i){
			node y=e2[u.id][i];
			if (done[y.to]) continue;
			if (dis2[y.to]> u.n_dis+y.w){
				dis2[y.to]=u.n_dis+y.w;
				q2.push(s_node(y.to,dis2[y.to])); 
			}
		}
	}
}

signed main(){
	cin>>n>>m;
	for (int i=0;i<m;++i){
		int a,b,c;
		cin>>a>>b>>c;
		e1[a].push_back(node(b,c));
		e2[b].push_back(node(a,c));
	}
	dijkstra1();
	int res=0;
	for (int i=1;i<=n;++i){
		res+=dis1[i];
	}
	dijkstra2();
	for (int i=1;i<=n;++i){
		res+=dis2[i];
	}
	cout<<res;
}
炸铁路https://www.luogu.com.cn/problem/P1656

题目描述

A 国派出将军 uim,对 B 国进行战略性措施,以解救涂炭的生灵。

B 国有 �n 个城市,这些城市以铁路相连。任意两个城市都可以通过铁路直接或者间接到达。

uim 发现有些铁路被毁坏之后,某两个城市无法互相通过铁路到达。这样的铁路就被称为 key road。

uim 为了尽快使该国的物流系统瘫痪,希望炸毁铁路,以达到存在某两个城市无法互相通过铁路到达的效果。

然而,只有一发炮弹(A 国国会不给钱了)。所以,他能轰炸哪一条铁路呢?

输入格式

第一行 �,� (1≤�≤150n,m (1≤n≤150,1≤�≤5000)1≤m≤5000),分别表示有 �n 个城市,总共 �m 条铁路。

以下 �m 行,每行两个整数 �,�a,b,表示城市 �a 和城市 �b 之间有铁路直接连接。

输出格式

输出有若干行。

每行包含两个数字 �,�a,b,其中 �<�a<b,表示 〈�,�〉〈a,b〉 是 key road。

请注意:输出时,所有的数对 〈�,�〉〈a,b〉 必须按照 �a 从小到大排序输出;如果�a 相同,则根据 �b 从小到大排序。

输入输出样例

输入 #1复制

6 6
1 2
2 3
2 4
3 5
4 5
5 6

输出 #1复制

1 2
5 6

思路:用并查集,先每次循环去掉一个遍,然后验证一边是否成立

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N=200;
int n,m;

struct node{
	int from;
	int to;
}a[5005];

bool cmp(const node& a, const node& b){
	if (a.from==b.from) return a.to<b.to;
	else return a.from<b.from;
}

int f[N],cnt=0;

int find(int x){
	if (f[x]==x){
		return x;
	}else if (f[x]!=x){
		f[x]=find(f[x]);
		return f[x];
	}
}

node b[5005];

void unionn(int i,int j){
	f[find(i)]=find(j);
}

void check(){
	for (int i=1;i<=m;++i){
		for (int i=1;i<=n;++i) f[i]=i;
		for (int j=1;j<=m;++j){
			if (i==j)continue;
			unionn(a[j].from,a[j].to);
		}
		for (int k=1;k<n;++k){
			if (find(k)!=find(k+1)){
				cnt++;
				b[cnt].from=a[i].from;
				b[cnt].to=a[i].to;
				break;
			}
		}
	}
	for (int i=1;i<=cnt;++i){
		if (b[i].from>b[i].to){
			int tmp=b[i].from;
			b[i].from=b[i].to;
			b[i].to=tmp;
		}
	}
	sort(b+1,b+1+cnt,cmp);
	for (int i=1;i<=cnt;++i){
		cout<<b[i].from<<" "<<b[i].to<<endl;
	}
}

signed main(){
	cin>>n>>m;
	for (int i=1;i<=m;++i){
		cin>>a[i].from>>a[i].to;
	}
	sort(a+1,a+1+m,cmp);
	check();
}
统计方形(数据加强版)https://www.luogu.com.cn/problem/P2241

题目背景

1997年普及组第一题

题目描述

有一个 �×�n×m 方格的棋盘,求其方格包含多少正方形、长方形(不包含正方形)。

输入格式

一行,两个正整数 �,�n,m(�≤5000,�≤5000n≤5000,m≤5000)。

输出格式

一行,两个正整数,分别表示方格包含多少正方形、长方形(不包含正方形)。

输入输出样例

输入 #1复制

2 3

输出 #1复制

8 10

思路:用数学的想法,在n×m的棋盘中,一个可以有C_{n+1}^{2}\textrm{}×C_{m+1}^{2}\textrm{}个矩形,然后正方形的最大边长是到min{m,n},所以正方形的个数是\sum_{1}^{n}(n+1-i)(m+1-i)(这里假定n<m),所以矩形的数量减去正方形就是长方形的数量

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

int n,m;

signed main(){
	cin>>n>>m;
	int cnt=0;
	int x=((n+1)*n/2)*((m+1)*m/2);
	for (int i=1;i<=min(m,n);++i){
		cnt+=(n-i+1)*(m-i+1);
	}
	cout<<cnt<<" "<<x-cnt;
}
滑雪https://www.luogu.com.cn/problem/P1434

题目描述

Michael 喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:

1   2   3   4   5
16  17  18  19  6
15  24  25  20  7
14  23  22  21  8
13  12  11  10  9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 24−17−16−124−17−16−1(从 2424 开始,在 11 结束)。当然 2525-2424-2323-……-33-22-11 更长。事实上,这是最长的一条。

输入格式

输入的第一行为表示区域的二维数组的行数 �R 和列数 �C。下面是 �R 行,每行有 �C 个数,代表高度(两个数字之间用 11 个空格间隔)。

输出格式

输出区域中最长滑坡的长度。

输入输出样例

输入 #1复制

5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

输出 #1复制

25

说明/提示

对于 100%100% 的数据,1≤�,�≤1001≤R,C≤100。

思路:记忆化+dfs,每个点来一遍dfs,就可以找到最大长度了,记忆化可以减少时间消耗

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N =105;
int a[N][N],s[N][N];
int m,n;

int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}};

void dfs(int x,int y){
	if (s[x][y]) return;
	s[x][y]=1;
	for (int i=0;i<4;++i){
		int xx=x+dir[i][0],yy=y+dir[i][1];
		if (xx < 1 || xx >m || yy<1 || yy >n) continue;
		if (a[x][y]>a[xx][yy]){
			dfs(xx,yy);
			s[x][y]=max(s[x][y],s[xx][yy]+1);
		}
		
	}
}

signed main(){
	cin>>m>>n;
	for (int i=1;i<=m;++i){
		for (int j=1;j<=n;++j){
			cin>>a[i][j];
		}
	}
	int ans=0;
	for (int i=1;i<=m;++i){
		for (int j=1;j<=n;++j){
			dfs(i,j);
			ans=max(ans,s[i][j]);
		}
	}
	cout<<ans;
}
小车问题https://www.luogu.com.cn/problem/P1258

题目描述

甲、乙两人同时从 A 地出发要尽快同时赶到 B 地。出发时 A 地有一辆小车,可是这辆小车除了驾驶员外只能带一人。已知甲、乙两人的步行速度一样,且小于车的速度。问:怎样利用小车才能使两人尽快同时到达。

输入格式

仅一行,三个实数,分别表示 AB 两地的距离 �s,人的步行速度 �a,车的速度 �b。

输出格式

两人同时到达 B 地需要的最短时间,保留 66 位小数。

输入输出样例

输入 #1复制

120 5 25

输出 #1复制

9.600000

说明/提示

数据规模与约定

对于 100%100% 的数据,保证 0≤�,�,�≤1090≤s,a,b≤109。

思路:解方程

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

double s,a,b;

signed main(){
	cin>>s>>a>>b;
	double t=((a+3*b)/(b*(3*a+b)))*s;
	printf("%.6lf",t);
}
ACMhttps://www.luogu.com.cn/problem/P7793

题目背景

Zagreb 大学的团队的成员 Stjepan、Ivan 和 Gustav 正在摩洛哥参加 ACM 国际大学生程序设计竞赛的世界决赛。他们的技术指导 Goran 想出了一个无敌的策略,用于解决决赛中的题目。

题目描述

在一开始,每个团队成员迅速估计 �n 道题目中每题的难度。这些难度用 11 到 55 的数字描述,数字越大,难度也就越大。

在这之后,他们之间将分配任务。为了简单起见,任务阵列将被分成三部分,以便每个团队成员得到一个非空的连续任务序列来思考。这种分配是为了使估计的难度之和最小,而只计算被分配到该任务的团队成员的估计难度值。你的任务是计算这个最小的可能总和。

输入格式

输入共四行。

第一行输入一个整数 �n,表示问题的数量。
第二到第四行,第 �+1i+1 行 �n 个整数 ��,1,��,2,…,��,�di,1​,di,2​,…,di,n​,表示第 �i 号成员对于这 �n 道题目估计的难度。

输出格式

输出仅一行,一个整数,表示最小可能的估计难度总和。

输入输出样例

输入 #1复制

3
1 3 3
1 1 1
1 2 3

输出 #1复制

4

输入 #2复制

7
3 3 4 1 3 4 4
4 2 5 1 5 5 4
5 5 1 3 4 4 4

输出 #2复制

19

说明/提示

【样例 1 解释】

给第 11 号成员分配第 11 题,给第 22 号成员分配第 33 道题,给第 33 号成员分配第 22 道题。这样分配的难度总和为 1+1+2=41+1+2=4。可以证明没有难度总和更小的分配方案。

【数据范围】

对于所有数据,3⩽�⩽1.5×1053⩽n⩽1.5×105,1⩽��,�⩽51⩽di,j​⩽5。

思路:动态规划,遍历所有的情况,因为一共的三个人,所以C_{3}^{1}\textrm{}C_{2}^{1}\textrm{}一共6种情况(需要在意顺序)确定状态转移方程:可以从上一个编号的人或自己做上一题进行转移

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N=2e5+5;

int n,dp[4][N],f[4][N],minn=INF;

void dfs(int a,int b,int c){
	memset(dp,0x3f,sizeof(dp));
	dp[a][1]=f[a][1];
	for (int i=2;i<=n;++i){
		dp[a][i]=dp[a][i-1]+f[a][i];
		dp[b][i]=min(dp[a][i-1],dp[b][i-1])+f[b][i];
		dp[c][i]=min(dp[b][i-1],dp[c][i-1])+f[c][i];
	}
	minn=min(minn,dp[c][n]);
}

signed main(){
	cin>>n;
	for (int i=1;i<=3;++i){
		for (int j=1;j<=n;++j){
			cin>>f[i][j];
		}
	}
	dfs(1,2,3);
	dfs(1,3,2);
	dfs(2,1,3);
	dfs(2,3,1);
	dfs(3,2,1);
	dfs(3,1,2);
	cout<<minn;
}
奶牛的耳语https://www.luogu.com.cn/problem/P1296

题目描述

在你的养牛场,所有的奶牛都养在一排呈直线的牛栏中。一共有 �n 头奶牛,其中第 �i 头牛在直线上所处的位置可以用一个整数坐标 ��(0≤��≤108)pi​(0≤pi​≤108) 来表示。在无聊的日子里,奶牛们常常在自己的牛栏里与其它奶牛交流一些八卦新闻。每头奶牛发出的声音响度是一样的,而由于声波的能量衰减,某头奶牛发出的声音只能被与它距离不超过 �(0≤�≤104)d(0≤d≤104) 的奶牛所听到,这样这对奶牛就称为可以相互交流的。现在给出所有奶牛的位置和声音所能传播的最远距离 �d ,请你编个程序来计算你的养牛场里究竟有多少对可以相互交流的奶牛。

输入格式

第一行包含两个整数 �,�n,d。

第二行包含 �n 个整数,每个整数都是一个坐标 ��pi​,描述一头奶牛在直线上的位置。

输出格式

一个数,表示养牛场中可以相互交流奶牛的对数。

输入输出样例

输入 #1复制

5 10
10 12 16 37 40

输出 #1复制

4

说明/提示

数据规模

对于 40%40% 的数据,1≤�≤1031≤n≤103。

对于 100%100% 的数据,1≤�≤1061≤n≤106。

思路:运用二分的思想,先对数组排序,然后用二分找到第一个听不见的位置,然后,加到计数器里面

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N=1e6+5;

int n,d,a[N];

signed main(){
	cin>>n>>d;
	for (int i=1;i<=n;++i) cin>>a[i];
	sort(a+1,a+1+n);
	int ans=0;
	for (int i=1;i<=n;++i){
		int p=upper_bound(a+i+1,a+1+n,a[i]+d)-a;
		ans+=p-i-1;
	}
	cout<<ans;
}
计算器的改良https://www.luogu.com.cn/problem/P1022

题目背景

NCL 是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能。实验室将这个任务交给了一个刚进入的新手 ZL 先生。

题目描述

为了很好的完成这个任务,ZL 先生首先研究了一些一元一次方程的实例:

  • 4+3�=84+3x=8。

  • 6�−5+1=2−2�6a−5+1=2−2a。

  • −5+12�=0−5+12y=0。

ZL 先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数、小写字母及 +-= 这三个数学符号(当然,符号“-”既可作减号,也可作负号)。方程中并没有括号,也没有除号,方程中的字母表示未知数。

你可假设对键入的方程的正确性的判断是由另一个程序员在做,或者说可认为键入的一元一次方程均为合法的,且有唯一实数解。

输入格式

一个一元一次方程。

输出格式

解方程的结果(精确至小数点后三位)。

输入输出样例

输入 #1复制

6a-5+1=2-2a

输出 #1复制

a=0.750

思路:模拟

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N=100;

int l;
double x,flag,mid,a[N];
char c,p;


signed main(){
	l=1,flag=1;
	while (c!='='){
		c=getchar();
		if (c=='+'){
			flag=1;
			l++;
		}else if (c=='-'){
			flag=-1;
			l++;
		}
		if (c>='0' && c<='9'){
			if (a[l]==0){
				a[l]+=(c-'0')*flag;
			}else{
				a[l]=a[l]*10+(c-'0')*flag;
			}
		}
		if (c>='a' && c<='z'){
			p=c;
			if (a[l]==0) x+=flag;
			else x+=a[l];
			a[l]=0;
			l--;
		}
	}
	mid=l,l++,flag=1;
	while (c!='\n'){
		c=getchar();
		if (c=='+'){
			flag=1;
			l++;
		}else if (c=='-'){
			flag=-1;
			l++;
		}
		if (c>='0' && c<='9'){
			if (a[l]==0){
				a[l]+=(c-'0')*flag;
			}else{
				a[l]=a[l]*10+(c-'0')*flag;
			}
		}
		if (c>='a' && c<='z'){
			p=c;
			if (a[l]==0) x-=flag;
			else x-=a[l];
			a[l]=0;
			l--;
		}
	}
	int sum=0;
	for (int i=1;i<=l;++i){
		if (i<=mid){
			sum-=a[i];
		}else {
			sum+=a[i];
		}
	}
	if (!(sum/x)){
		printf("%c=0.000",p);
	}else {
		printf("%c=%.3lf",p,sum/x);
	}
}
L-shapeshttps://www.luogu.com.cn/problem/CF1722F

题目描述

An L-shape is a figure on gridded paper that looks like the first four pictures below. An L-shape contains exactly three shaded cells (denoted by *), which can be rotated in any way.

You are given a rectangular grid. Determine if it contains L-shapes only, where L-shapes can't touch an edge or corner. More formally:

  • Each shaded cell in the grid is part of exactly one L-shape, and
  • no two L-shapes are adjacent by edge or corner.

For example, the last two grids in the picture above do not satisfy the condition because the two L-shapes touch by corner and edge, respectively.

输入格式

The input consists of multiple test cases. The first line contains an integer �t ( 1≤�≤1001≤t≤100 ) — the number of test cases. The description of the test cases follows.

The first line of each test case contains two integers �n and �m ( 1≤�,�≤501≤n,m≤50 ) — the number of rows and columns in the grid, respectively.

Then �n lines follow, each containing �m characters. Each of these characters is either '.' or '*' — an empty cell or a shaded cell, respectively.

输出格式

For each test case, output "YES" if the grid is made up of L-shape that don't share edges or corners, and "NO" otherwise.

You can output the answer in any case (for example, the strings "yEs", "yes", "Yes" and "YES" will be recognized as a positive answer).

题意翻译

L形在网格纸上形如下面的前四张图片。L形正好包含三个阴影单元(用*表示),可以以任何方式旋转。

现给你一个矩形网格。确定它是否仅包含L形,其中L形不能接触边或角,也就是说网格中的每个阴影单元正好是一个L形的一部分,并且没有两个L形通过边或角相邻。

例如,上图中的最后两个网格不满足条件,因为两个L形分别通过角和边缘接触。

如果网格满足条件,则输出“YES”,否则输出“NO”。

输入输出样例

输入 #1复制

10
6 10
........**
.**......*
..*..*....
.....**...
...*.....*
..**....**
6 10
....*...**
.**......*
..*..*....
.....**...
...*.....*
..**....**
3 3
...
***
...
4 4
.*..
**..
..**
..*.
5 4
.*..
**..
....
..**
..*.
3 2
.*
**
*.
2 3
*..
.**
3 2
..
**
*.
3 3
.**
*.*
**.
3 3
..*
.**
..*

输出 #1复制

YES
NO
NO
NO
YES
NO
NO
YES
NO
NO

思路:把*都成1,其他都是0,找到特殊的四种情况,然后判断,把可以成立的变成0,最后遍历一边数组,如果还有1那就不行

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N=55;

int t,n,m,a[N][N];

void check(int i,int j){
	if (a[i+1][j] && a[i+1][j+1] && !a[i-1][j-1] && !a[i-1][j] && !a[i-1][j+1] && !a[i][j-1]  && !a[i][j+1] && !a[i][j+2]
	&& !a[i+1][j-1] && !a[i+1][j+2] && !a[i+2][j-1] && !a[i+2][j]  && !a[i+2][j+1] && !a[i+2][j+2])
	{
		a[i][j]=a[i+1][j] = a[i+1][j+1] = 0;
		return;
	}
	if (a[i][j+1] && a[i+1][j+1] && !a[i-1][j-1] && !a[i-1][j] && !a[i-1][j+1] && !a[i-1][j+2] && !a[i][j-1]  && !a[i][j+2]
	&& !a[i+1][j-1] && !a[i+1][j] && !a[i+1][j+2] && !a[i+2][j]  && !a[i+2][j+1] && !a[i+2][j+2])
	{
		a[i][j+1]=a[i+1][j+1] = a[i][j] = 0;
		return;
	}
	if (a[i+1][j] && a[i+1][j-1] && !a[i-1][j-1] && !a[i-1][j] && !a[i-1][j+1] && !a[i][j-2] && !a[i][j-1]  && !a[i][j+1]
	&& !a[i+1][j-2] && !a[i+1][j+1] && !a[i+2][j-1] && !a[i+2][j]  && !a[i+2][j+1] && !a[i+2][j-2])
	{
		a[i+1][j]=a[i+1][j-1] = a[i][j] = 0;
		return;
	}
	if (a[i][j+1] && a[i+1][j] && !a[i-1][j-1] && !a[i-1][j] && !a[i-1][j+1] && !a[i-1][j+2] && !a[i][j-1]  && !a[i][j+2]
	&& !a[i+1][j-1] && !a[i+1][j+1] && !a[i+1][j+2]&& !a[i+2][j-1] && !a[i+2][j]  && !a[i+2][j+1] )
	{
		a[i][j]=a[i+1][j] = a[i][j+1] = 0;
		return;
	}
}

signed main(){
	cin>>t;
	while (t--){
		cin>>n>>m;
		memset(a,0,sizeof(a));
		for (int i=1;i<=n;++i){
			for (int j=1;j<=m;++j){
				char c;	cin>>c;
				if (c=='*') a[i][j]=1;
			}
		}
		for (int i =1 ;i<=n ;++i ){
			for (int j =1 ; j<=m ;++ j){
				if (a[i][j] == 1) check(i,j);
			}
		}
		bool flag=true;
		for (int i =1 ;i<=n ;++i ){
			for (int j =1 ; j<=m ;++ j){
				if (a[i][j] == 1){
					flag=false;
					break;
				}
			}
			if (!flag) break;
		}
		if (!flag) cout<<"NO"<<endl;
		else cout<<"YES"<<endl;
	}
}
Alternating Heightshttps://www.luogu.com.cn/problem/P10050

题目描述

Troy 计划给 CCO 的学生拍一张合影,他向你寻求帮助。

有 �K 个学生,编号从 11 到 �K。Troy 忘记了学生的身高,但他记得没有两个学生的身高相同。

Troy 有一个序列 �1,�2,…,��A1​,A2​,…,AN​,表示合影中从左到右的学生顺序。一个学生可能在 �A 中出现多次。你不确定这张合影会怎么拍,但你不愿意认为 Troy 犯了错误。

Troy 会给你 �Q 个形式为 �,�x,y 的询问,每个询问为「给定学生序列 ��,��+1,…,��Ax​,Ax+1​,…,Ay​,他们的身高能否形成一个交替序列?」更具体地说,我们用 ℎ�hi​ 表示第 �i 个学生的身高。如果存在一种身高分配ℎ1,ℎ2,…,ℎ�h1​,h2​,…,hK​,使得 ℎ��>ℎ��+1<ℎ��+2>ℎ��+3<…ℎ��hAx​​>hAx+1​​<hAx+2​​>hAx+3​​<…hAy​​,回答 YES;否则回答 NO

注意,每个查询都是独立的:也就是说,询问 �i 的身高分配与询问 �j 的身高分配无关 (�≠�)(i=j)。

输入格式

第一行包含三个用空格分隔的整数 �,�N,K 和 �Q。

第二行包含 �N 个整数,表示 �1,�2,…,��(1≤��≤�)A1​,A2​,…,AN​(1≤Ai​≤K)。

接下来的 �Q 行,每行包含两个用空格分隔的整数 �x 和 �(1≤�<�≤�)y(1≤x<y≤N),表示一组查询。

输出格式

输出 �Q 行。第 �i 行,输出 YES 或者 NO,表示 Troy 的第 �i 个查询的答案。

输入输出样例

输入 #1复制

6 3 3
1 1 2 3 1 2
1 2
2 5
2 6

输出 #1复制

NO
YES
NO

说明/提示

样例说明

对于第一个询问,不可能有 ℎ1>ℎ1h1​>h1​,所以答案是 NO

对于第二个询问,ℎ1>ℎ2<ℎ3>ℎ1h1​>h2​<h3​>h1​ 的一种方案是 ℎ1=160 cm,ℎ2=140 cm,ℎ3=180 cmh1​=160 cm,h2​=140 cm,h3​=180 cm。另一种方案是 ℎ1=1.55 m,ℎ2=1.473 m,ℎ3=1.81 mh1​=1.55 m,h2​=1.473 m,h3​=1.81 m。

对于第三个询问,不可能同时有 ℎ1>ℎ2h1​>h2​ 和 ℎ1<ℎ2h1​<h2​。

数据范围

对于所有的数据,有 2≤�≤30002≤N≤3000,2≤�≤�2≤K≤N,1≤�≤1061≤Q≤106。

子任务编号

分值

�N

�K

�Q

11

1616

2≤�≤30002≤N≤3000

�=2K=2

1≤�≤1061≤Q≤106

22

2424

2≤�≤5002≤N≤500

2≤�≤min⁡(�,5)2≤K≤min(N,5)

1≤�≤1061≤Q≤106

33

2828

2≤�≤30002≤N≤3000

2≤�≤�2≤K≤N

1≤�≤20001≤Q≤2000

44

3232

2≤�≤30002≤N≤3000

2≤�≤�2≤K≤N

1≤�≤1061≤Q≤106

思路:看成图,如果存在环,那就无法成立,用拓扑排序判断是否成环,暴力搜会超时,用二分的思想,固定左端点,然后找到以此为左端点的最大区间长度

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f

const int N=3005;

int n,k,Q,a[N],in[N],num[N],g[N][N],max_len[N];
queue<int>q;

bool check(int l,int r){	//拓扑排序 
	int sum=0;
	memset(in,0,sizeof(in));	//记录入度 
	memset(num,0,sizeof(num));	//记录相邻的节点数 
	while (!q.empty()) q.pop();
	for (int i=l+1;i<=r;i+=2){		//指向高的 
		if (i-1>0){
			g[a[i]][++num[a[i]]]=a[i-1];
			in[a[i-1]]++;
		}
		if (i+1<=r){
			g[a[i]][++num[a[i]]]=a[i+1];
			in[a[i+1]]++;
		}
	}
	for (int i=1;i<=k;++i){	//入度为0就入队 
		if (!in[i]) q.push(i);
	}
	while (!q.empty()){
		int p=q.front(); q.pop();
		sum++;
		for (int i=1;i<=num[p];++i){
			in[g[p][i]]--;	//出队后,相邻点的入度减1 
			if (!in[g[p][i]]) q.push(g[p][i]);
 		}
	}
	return sum==k;
}

int erfen(int m){
	int l=m,r=n,maxn=0;
	while (l<=r){
		int mid=l+r>>1;
		if (check(m,mid)){	//以m为左端点的最长区间 
			maxn=max(maxn,mid);
			l=mid+1;
		}
		else r=mid-1;
	}
	return maxn;
}

signed main(){
	cin>>n>>k>>Q;
	for (int i=1;i<=n;++i) cin>>a[i];
	for (int i=1;i<=n;++i) max_len[i]=erfen(i);
	for (int i=1;i<=Q;++i){
		int x,y;
		cin>>x>>y;
		if (max_len[x]<y) cout<<"NO"<<endl;
		else cout<<"YES"<<endl;
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/391463.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二叉树前序中序后序遍历(非递归)

大家好&#xff0c;又和大家见面啦&#xff01;今天我们一起去看一下二叉树的前序中序后序的遍历&#xff0c;相信这个对大家来说是信手拈来&#xff0c;但是&#xff0c;今天我们并不是使用常见的递归方式来解题&#xff0c;我们采用迭代方式解答。我们先看第一道前序遍历 1…

基于Robei EDA实现FIFO(非IP核)及FIFO求和

一、FIFO简介 FIFO&#xff08; First in First out&#xff09; 使用在需要产生数据接口的部分&#xff0c;用来存储、缓冲在两个异步 时钟之间的数据传输。在异步电路中&#xff0c;由于时钟之间周期和相位完全独立&#xff0c;因此数据丢失概 率不为零。使用 FIFO 可以在两个…

【ChatIE】论文解读:Zero-Shot Information Extraction via Chatting with ChatGPT

文章目录 介绍ChatIEEntity-Relation Triple Extration (RE)Named Entity Recognition (NER)Event Extraction (EE) 实验结果结论 论文&#xff1a;Zero-Shot Information Extraction via Chatting with ChatGPT 作者&#xff1a;Xiang Wei, Xingyu Cui, Ning Cheng, Xiaobin W…

【电源】POE系统供电原理(二)

转载本博客文章&#xff0c;请注明出处 ​ 上一篇文章中&#xff0c;有提到POE系统工作原理及动态检测机制&#xff0c;下面我们继续介绍受电端PD技术及原理。POE供电系统包含PSE、PD及互联接口部分组成&#xff0c;如下图所示。 图1 POE供电系统 PSE控制器的主要作用&#xff…

无人机基本知识,无人机遥控器功能详解与调试方法

无人机作为一种新兴的飞行器&#xff0c;近年来在各个领域得到了广泛的应用。而无人机遥控器则是控制无人机飞行的重要工具。 无人机遥控器是一种无线设备&#xff0c;通过它来远程控制无人机的飞行。遥控器通常包括一个或多个摇杆&#xff0c;用于控制无人机的各种动作&#x…

FL Studio 21中文破解激活版2024免费下载安装图文教程

FL Studio 21.2.1.3859中文破解激活版是我见过更新迭代最快的宿主软件&#xff0c;没有之一。FL Studio12、FL Studio20、FL Studio21等等。有时甚至我刚刚下载好了最新版本&#xff0c;熟悉了新版本一些好用的操作&#xff0c;Fl Studio就又推出了更新的版本&#xff0c;而且F…

【STM32 CubeMX】串口编程DMA+IDLE中断

文章目录 前言一、为什么要引入IDLE中断二、IDLE中断使用方式2.1 接收的三种情况2.2 函数的使用查询方式中断方式DMA方式分析一个问题 总结 前言 在嵌入式系统中&#xff0c;串口通信是一项关键的任务&#xff0c;而使用DMA&#xff08;直接内存访问&#xff09;结合IDLE中断进…

基于springboot特产销售平台源码和论文

“互联网”的战略实施后&#xff0c;很多行业的信息化水平都有了很大的提升。但是目前很多藏区特产销售信息仍是通过人工管理的方式进行&#xff0c;需要在各个岗位投入大量的人力进行很多重复性工作&#xff0c;使得对人力物力造成诸多浪费&#xff0c;工作效率不高等情况&…

【初始RabbitMQ】工作队列的实现

工作队列 工作队列&#xff08;又称为任务队列&#xff09;的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。 相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进 程将弹出任务并最终执行作业。当有多个工作线程…

电脑屏幕录制工具 Top10 榜单,免费无水印方法集

随着媒体行业的突飞猛进&#xff0c;不同服务之间对有效屏幕录制的竞争日益激烈。这导致市场上出现了质量参差不齐的屏幕录像机。特别是有些录屏器会自动给你录制的视频加上水印&#xff0c;给需要在公共场合使用的人留下不专业的印象。除此之外&#xff0c;它们甚至不能保护您…

【Google Bard】免费生成图像——功能和使用方法详解

Google Bard 关于Bard 图片生成功能打开Bard通过Bard来生成图片Bard Vs Bing Vs Dall-EBard的生成结果Bing的生成结果Dall-E 的生成结果 总结 关于Bard 图片生成功能 Google在2月1日&#xff08;当地时间&#xff09;宣布&#xff0c;其对话型AI“Bard”新增了图像生成功能。 …

Mysql——update更新数据的方式

注&#xff1a;文章参考&#xff1a; MySQL 更新数据 不同条件(批量)更新不同值_update批量更新同一列不同值-CSDN博客文章浏览阅读2w次&#xff0c;点赞20次&#xff0c;收藏70次。一般在更新时会遇到以下场景&#xff1a;1.全部更新&#xff1b;2.根据条件更新字段中的某部分…

MATLAB离线文档安装

MATLAB离线文档安装 来源于最全matlab安装离线文档教程只是对内容进行了精简&#xff0c;同时更方便查找 一、下载离线文档 我上传的2023b离线文档 提供本体属于违规行为&#xff0c;本体下载链接已删除 为方便已安装好软件的朋友想安装离线帮助文档&#xff0c;由于官网下载…

模型 IPO(输入、处理、输出)学习模型

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。重在提升认知。信息转化与传递。 1 模型 IPO(输入、处理、输出)学习模型的应用 1.1 项目管理知识体系 PMBOK 中的IPO应用 在项目管理领域&#xff0c;PMBOK&#xff08;Project Management Body of Know…

究极小白如何自己搭建一个自动发卡网站-独角数卡

本人从来没接触过建站&#xff0c;我之前都是在TB上花90叫别人给我搭建的网站&#xff0c;前几天这个TB店倒闭跑路了&#xff0c;而我的发卡网也打不开了&#xff0c;没办法&#xff0c;逼上梁山&#xff0c;自己捣鼓出来了&#xff01;下面是2023/4/2自己建好的&#xff01; …

STM32F1 - 系统时钟SysTick

SysTick 1> SysTick硬件框图2> SysTick的时钟源3> 1ms定时_中断方式4> 思考&#xff1a;无符号数 0 - 255 ?相关资料 1> SysTick硬件框图 SysTick属于Cotex-M3&#xff0c;是CPU外设&#xff1b; SysTick: 位宽24bit&#xff0c; 递减计数&#xff0c;自动重装…

《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)

文章目录 2.1 条件语句&#xff1a;决策的艺术2.1.1 基础知识讲解2.1.2 重点案例&#xff1a;用户角色权限判断实现用户角色权限判断扩展功能实现代码功能扩展&#xff1a;添加或删除用户 2.1.3 拓展案例 1&#xff1a;成绩等级判断实现成绩等级判断功能实现代码扩展功能&#…

【开源图床】使用Typora+PicGo+Github+CDN搭建个人博客图床

准备工作&#xff1a; 首先电脑得提前完成安装如下&#xff1a; 1. nodejs环境(node ,npm):【安装指南】nodejs下载、安装与配置详细教程 2. Picgo:【安装指南】图床神器之Picgo下载、安装与配置详细教程 3. Typora:【安装指南】markdown神器之Typora下载、安装与无限使用详细教…

canal监听binlog记录业务数据的变更;canalAdmin对instance做web配置

概述 平时在开发中会通过logback打印一些开发日志&#xff0c;有时也会需要记录一些业务日志&#xff0c;简单的就直接用log记录一下&#xff0c;但是系统中需要记录日志的地方越来越多时&#xff0c;不能每个地方都写一套log记录&#xff1b; 由于平常用的大多都是mysql&…

Linux进程间通信(三)-----System V消息队列

消息队列的概念及原理 消息队列实际上就是在系统当中创建了一个队列&#xff0c;队列当中的每个成员都是一个数据块&#xff0c;这些数据块都由类型和信息两部分构成&#xff0c;两个互相通信的进程通过某种方式看到同一个消息队列&#xff0c;这两个进程向对方发数据时&#x…