20250814 OI 总结

Problem T1 T2 T3 T4 T5 T6 all
want scores 100pts 100pts 60pts 40pts 60pts 0pts 360pts
scores 100pts 0pts 60pts 0pts 60pts 0pts 260pts

T3

爆零原因:输出制表符错了

正解:反向建图,这样每个点只会跑一次 dfs;

代码:(下次再也不用快读了)

#include <stdio.h>
#include <queue>
#include <vector>
#define ll long long
#define ull unsigned long long
#define int int
#define db double
using namespace std;
const int MAXN = 1e5 + 7;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int n,m;
vector<int>e[MAXN];
int dis[MAXN];
int vis[MAXN];
int read(){
	int x = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9'){ch = getchar();}
	while(ch >= '0' && ch <= '9'){x=x*10+(ch-'0');ch = getchar();}
	return x;
}
void dfs(int x,int root){
    if(vis[x]) return;
    vis[x] = root;
    dis[x] = 1;
    for(auto y : e[x]){
        if(!dis[y]){
            dfs(y,root);
        }
    }
}
int main(){
	n = read(),m = read();
	for(int i = 1;i <= m;i++){
		int x,y;
		x = read(),y = read();
		e[y].push_back(x);
	}
	for(int i = n;i >= 1;i--){
		dfs(i,i);
	}
    for(int i = 1;i <= n;i++)
        printf("%d ",vis[i]);
	return 0;
}

T4

死因:反转数组翻错了

思路:按照题目即可

方法总结:

  1. 模拟题先拟好思路在写代码
  2. 尽量一次写对,不然调试可是很爽的

代码:

#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define ull unsigned long long
#define int int
#define db double
const int MAXN = 50 + 7;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int t,n,k;
char s[MAXN][MAXN],c[MAXN][MAXN];
char b[MAXN][MAXN],nm[MAXN][MAXN];
void fanzhuan(){
	for(int i = 1;i <= k;i++)
		for(int j = 1;j <= k;j++)
			b[j][k-i+1] = c[i][j];
	for(int i = 1;i <= k;i++)
		for(int j = 1;j <= k;j++)
			c[i][j] = b[i][j];
}
bool check(int x,int y){
	for(int i = 1,ii = x;i <= k;ii++,i++){
		for(int j = 1,jj = y;j <= k;j++,jj++){
			if(s[ii][jj] == '.' && c[i][j] == '*')
				return false;
		}
	}
	return true;
}
void draw(int x,int y){
	for(int i = 1,ii = x;i <= k;ii++,i++){
		for(int j = 1,jj = y;j <= k;j++,jj++){
			if(c[i][j] != '.'){
				nm[ii][jj] = '*';
			}
		}
	}
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				nm[i][j] = '.';
			}
		}
		for(int i = 1;i <= n;i++) 
			scanf("%s",s[i]+1);
		scanf("%d",&k);
		for(int i = 1;i <= k;i++) 
			scanf("%s",c[i]+1);
		for(int i = 1;i <= n - k + 1;i++){
			for(int j = 1;j <= n - k + 1;j++){
				for(int l = 1;l <= 4;l++){
					fanzhuan();
					if(check(i,j)){
						draw(i,j);
					}
				}
			}
		}
		bool flag = 1;
		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				if(s[i][j] != nm[i][j]){
					flag = 0;
					break;
				}
			}	
		}
		printf("%s\n",(flag) ? "YES" : "NO");
	}	
	return 0;
}

T5

打表过样例,暴力出奇迹

死因:写完暴力没想出办法(原来写的二分,证明发现不行)

通过打表严谨分析,可以得出,只要求出顺序对的个数就好了。

代码:

#include <bits/stdc++.h>

using namespace std;
int n;
const int MAXN = 1e5 + 7;
int a[MAXN];
int c[MAXN]; 
long long ans = 0;
void qsort(int l,int r){
	if(l == r){
		return;
	}
	int mid = (l + r) / 2;
	int i = l,j = mid + 1,k = l;
	qsort(i,mid),qsort(mid+1,r);
	while(i <= mid && j <= r){
		if(a[i] <= a[j]){
			c[k++] = a[i++];
            ans += r - j + 1;
		}else{
			c[k++] = a[j++];
		}
	}
	while(i <= mid){
		c[k++] = a[i++];
	}
	while(j <= r){
		c[k++] = a[j++];
	}
	for(int c1 = l;c1 <= r;c1++){
		a[c1] = c[c1];
	}
}
int k;
int main()
{
	cin >> n >> k;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
        a[i] -= k;
        a[i] += a[i-1];
	}
	qsort(0,n);
	cout << ans << endl;	
	return 0;
}

T6

死因:最小生成树不会(虽然今天学了)

怀疑这是原题搬过来的,点一下复制题目呃呃呃

代码:

#include <bits/stdc++.h>

using namespace std;
#define ll long long
const int INF  = 0x3f3f3f3f;
const int MAXH = 2e5 + 7;
const int mod = 1e9 + 7;
int n,m;
struct node{
	int x,y,w;
	bool operator < (const node &x) const{
		return w < x.w;
	}
}e[MAXH];
int fa[MAXH];
int c[MAXH];
int find(int x){
	if(fa[x] == x)
		return x;
	return fa[x] = find(fa[x]);
}
int kruskal(){
	for(int i = 1;i <= n;i++)
		fa[i] = i;
	sort(e+1,e+m+1);
	int tot = n,ans = 0;
	for(int i = 1;i <= m;i++){
		int x = find(e[i].x),y = find(e[i].y);
		if(x != y){
			ans += e[i].w;
			tot--;
			fa[x] = y;
		}
	}
    return ans;
}
signed main()
{
	cin >> n >> m;
    int s = INF;
    for(int i = 1;i <= n;i++){
        cin >> c[i];
        s = min(s,c[i]);
    }
	for(int i = 1;i <= m;i++){
		cin >> e[i].x >> e[i].y >> e[i].w;
        e[i].w += e[i].w;
        e[i].w += c[e[i].x] + c[e[i].y];
	}
	int ans = kruskal();
	cout << ans + s;
	return 0;
}
posted @ 2025-08-14 20:54  Ruochen_xia  阅读(12)  评论(0)    收藏  举报