杭电暑期多校第一场

Mod, Or and Everything

请添加图片描述
题意
本题就是给一个数n,对所有小于它的数取模,然后进行或运算,这样我们一定可以找到一个模最大的数m并且它的模数一定是1~m
由于是或操作有一为一,于是我们可以将m转化成二进制,比如11001,它一定是00001~11001取模,每一位一定有大于一个的一,于是它的结果一定会将11001中的零变成一 所以结果为11111;

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
void solve() {
    long long n;
    scanf("%lld", &n);
    if (n <= 2) {
        printf("%d\n", 0);
        return;
    }
    long long s = n / 2 + 1;
    s = n % s;
    long long ans = 0;
    while (s>0) {
        s = s >> 1;
        ans = ans * 2 + 1;
    }
    printf("%lld\n", ans);
}
int main(){
    int t;
    scanf("%d", &t);
    while (t--)solve();
    return 0;
}

Minimum spanning tree

请添加图片描述
题意
这道题实际上是一个质数筛因为如果不是一个质数的话那么一定有一个因子可以和它相连,他们的边权(公倍数)一定为这个大的数
当这个数为质数时,为了使边权最小,就要使它与2相连请添加图片描述

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
void solve() {
    long long n;
    scanf("%lld", &n);
    if (n <= 2) {
        printf("%d\n", 0);
        return;
    }
    long long s = n / 2 + 1;
    s = n % s;
    long long ans = 0;
    while (s>0) {
        s = s >> 1;
        ans = ans * 2 + 1;
    }
    printf("%lld\n", ans);
}
int main(){
    int t;
    scanf("%d", &t);
    while (t--)solve();
    return 0;
}

KD-Graph

请添加图片描述
请添加图片描述
题意
给出n个点m条边,这些点分成k组,
如果p和q在同一组中,他们间一定有一条边小于等于一个数ans
如果p和q不在同一组中,他们间一定没有小于等于ans的一条边
现在要求我们求出这个最小的非负整数ans
我们可以先用一个结构体存每一条边的两个顶点和他们的边权,然后把他们以边权排序将相同边的归并到同一个集合中(顺序从小到大)如果其中满足了,就可以输出了,如果每条边遍历完之后仍然达不到我们期望的k组的话,就输出-1;(由于查询较多,我们要尽量减小复杂度,于是用并查集解决);

#include<iostream>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N = 1000010;
struct a {
	int u, v, c;
}gg[N];
int fa[N];
int n, m, k, t, ans, front;
bool cmp(a c1, a c2) {
	return c1.c < c2.c;
}
int find(int x) {
	if (fa[x] != x)fa[x] = find(fa[x]);
	return fa[x];
}
void solve() {
	scanf("%d%d%d", &n, &m, &k);
	ans = 0;
	front = n;
	for (int i = 1; i <= n; i++)fa[i] = i;
	for (int i = 1; i <= m; i++) {
		scanf("%d%d%d", &gg[i].u, &gg[i].v, &gg[i].c);
	}
	sort(gg + 1, gg + m + 1, cmp);
	for (int i = 1; i <= m; i++) {
		if (gg[i].c != gg[i - 1].c) {
			if (front == k) {
				printf("%d\n", ans);
				return;
			}
		}
		if (find(gg[i].u) == find(gg[i].v))continue;
		front--;
		fa[find(gg[i].u)] = find(gg[i].v);
		ans = gg[i].c;
	}
	printf("%d\n",front==k?ans:-1);
}
int main() {
	scanf("%d", &t);
	while (t--)solve();
	return 0;
}

Maximal submatrix

请添加图片描述
题意
给出一个n*m的矩阵,求其中不严格单调的矩阵的面积
转化为零一矩阵之后用悬线法或者是单调栈求出面积(题解的手动模拟单调栈太妙了,直接加进板子里面)
题解里面更妙的是只用了一个一维数组模拟出了每一行不严格单减的高度(乡下人第一次看到太妙了)

#include<bits/stdc++.h>
using namespace std;
const int mx = 5e3 + 10;
int a[mx][mx], b[mx][mx], h[mx];
int que[mx];
void solve() {
	int n, m;
	scanf("%d%d", &n, &m);
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			scanf("%d", &a[i][j]);
			b[i][j] = 0;
			if(i>1)b[i][j] = (a[i][j] >= a[i - 1][j]);
		}
	}//转化为零一矩阵
	for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(b[i][j]==0)h[j]=1;
            else h[j]++;
        }//每一层的高度
        int tot=0;
        h[m+1]=0;
        for(int j=1;j<=m+1;j++){
            while(tot&&h[que[tot]]>h[j]){
                ans=max(ans,(j-que[tot-1]-1)*h[que[tot]]);
                tot--;
            }
            que[++tot]=j;
        }
    }
    printf("%d\n",ans);//题解的精华部分;
}
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值