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();
}
}