Codeforces Round #580 (Div. 2)
选最大的两个数
#include <bits/stdc++.h>
#define sc scanf
#define pr printf
#define ll long long
using namespace std;
const int MAXN = 200005;
int a[200005], b[200005];
int main()
{
int n, m, t;
sc("%d", &n);
for (int i = 0; i < n; i++)
{
sc("%d", &a[i]);
}
sc("%d", &m);
for (int i = 0; i < m; i++)
{
sc("%d", &b[i]);
}
sort(a, a + n, [](int q, int w) {
return q > w;
});
sort(b, b + m, [](int q, int w) {
return q > w;
});
printf("%d %d", a[0], b[0]);
}
乱搞
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int aa[200000];
int book[30000];
int main()
{
int n;
scanf("%d", &n);
ll ans = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &aa[i]);
if (aa[i] < 0)
{
ans -= 1 + aa[i];
aa[i] = -1;
book[2]++;
continue;
}
else if (aa[i] > 0)
{
ans += aa[i] - 1;
aa[i] = 1;
book[1]++;
}
else
{
book[0]++;
}
}
if ((book[2] & 1) == 0)
ans += book[0];
else
{
if (book[0] != 0)
ans += book[0];
else
ans += 2;
}
printf("%lld", ans);
}
简单构造,偶数判掉,然后奇数,一前一后构造
#include <bits/stdc++.h>
#define sc scanf
#define pr printf
#define ll long long
using namespace std;
const int MAXN = 200005;
int a[MAXN];
int main()
{
int n;
sc("%d", &n);
if (n & 1)
{
puts("YES");
int cnt = 1;
for (int i = 1; i <= n; i++)
{
if (i & 1)
{
a[i] = cnt++;
a[i + n] = cnt++;
}
else
{
a[i + n] = cnt++;
a[i] = cnt++;
}
}
for (int i = 1; i <= 2 * n; i++)
{
printf("%d%c", a[i], i == 2 * n ? '\n' : ' ');
}
}
else
{
puts("NO");
}
}
给你n个点,每个点都有权值,两个点当且仅当(ai&aj)!=0时才会有边.
让你求最小的循环长度 (循环中的点要大于等于3)
点的权值的上限是1e18,比2^60小.
易得结论:n>120时必定存在一个循环长度为3的环
假设前60个点每个点都不会与其他点连边,这是最坏的情况,也就是每个点都是2的k次方这样子
那么后面不论加什么点都会与前面60个点的其中至少一个点连有边,再考虑最坏的情况,加入120
个点后恰好每两个点有边,此时再加入任意一个点,即存在一个环.
注意点的权值可以为0,把权值为0的点剔除就好.
对于n<=120 跑个floyd最小环
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAX = 1e3 + 5;
const ll INF = 0x3f3f3f3f;
const ll MAXN = 1e5 + 5;
ll n, m, book[MAX][MAX], dis[MAX][MAX];
ll A[MAXN], num = 0;
vector<ll> list1;
void solve() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%lld", &A[i]);
if (A[i] != 0) {
++num;
list1.push_back(A[i]);
}
}
n = list1.size();
for (int i = 1; i <= n; ++i) {
A[i] = list1[i - 1];
}
if (n > 120) {
printf("3\n");
return;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
book[i][j] = dis[i][j] = INF;
}
}
for (int i = 1; i <= n; ++i) {
for (int j = i + 1; j <= n; ++j) {
if ((A[i] & A[j]) != 0) {
ll a, b, c;
a = i, b = j, c = 1;
ll w = book[a][b];
dis[a][b] = dis[b][a] = book[a][b] = book[b][a] = min(w, c);
}
}
}
ll ans = INF;
for (ll k = 1; k <= n; ++k) {
for (ll i = 1; i <= n; ++i)
for (ll j = 1; j <= n; ++j)
if (i != j && j != k && i != k)
ans = min(ans, dis[i][j] + book[i][k] + book[k][j]);
for (ll i = 1; i <= n; ++i)
for (ll j = 1; j <= n; ++j)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
if (ans == INF) printf("-1\n");
else printf("%lld\n", ans);
}
int main(void)
{
solve();
return 0;
}
赛后把输出中间的空格删掉了,就过了,我寻思再给我两分钟,我就能过这题?
1、首先确认 位置是1,然后我们通过询问可以得到所有 位置的值
2、然后我们假设 位置是0,通过询问可以得到所有 位置的值
3、那么我们现在知道了所有 的值,和所有 的相对值,如果我们能知道 位置的某一个确定值,那么我们就可以确定矩阵
4、那么我们假设原矩阵为 A2 矩阵,将所有 位置的值取反的矩阵为 A1 矩阵
5、那么我们希望在A1和A2里面找到一个相对位置相同的串,使得在 A1 A2 中,一个是回文串,另一个不是,这样我们就可以在一次询问中得到某个 位置的确定值,然后判断一下这个位置的符号,不同就所有这个位置的元素取反,就可以AC。
#include <bits/stdc++.h>
#define sc scanf
#define pr printf
#define ll long long
using namespace std;
int a[55][55];
const int MAX = 1e3 + 5;
const int INF = 0x3f3f3f3f;
int color;
int A[MAX][MAX];
int A1[MAX][MAX], A2[MAX][MAX];
int N;
int DX[2] = { 0,1 }, DY[2] = { 1,0 };
int NOW1[4], NOW2[4];
int X1, Y1, X2, Y2;
bool FLAG = false;
bool VIS[MAX][MAX];
void dfs(int x, int y, int count) {
if (FLAG)
return;
if (count == 4) {
if (NOW1[1] == NOW1[2] && NOW1[0] == NOW1[3]) {
if (NOW2[1] != NOW2[2] || NOW2[0] != NOW2[3]) {
FLAG = true;
X2 = x, Y2 = y;
color = 1;
return;
}
}
if (NOW2[1] == NOW2[2] && NOW2[0] == NOW2[3]) {
if (NOW1[1] != NOW1[2] || NOW1[0] != NOW1[3]) {
FLAG = true;
X2 = x, Y2 = y;
color = 2;
return;
}
}
return;
}
for (int i = 0; i < 2; ++i) {
int numX = x + DX[i];
int numY = y + DY[i];
if (numX >= 1 && numX <= N && numY >= 1 && numY <= N && \
!VIS[numX][numY]) {
NOW1[count] = A1[numX][numY];
NOW2[count] = A2[numX][numY];
VIS[numX][numY] = true;
dfs(numX, numY, count + 1);
VIS[numX][numY] = false;
}
}
}
void solve() {
//sc("%d", &N);
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) {
A[i][j] = a[i][j];
if ((i + j) & 1) {
if (A[i][j] == 0)
A1[i][j] = 1, A2[i][j] = 0;
else
A1[i][j] = 0, A2[i][j] = 1;
}
else A1[i][j] = A2[i][j] = A[i][j];
}
}
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= N; ++j) {
// if(!((i+j)&1)){
// NOW1[0]=NOW2[0]=A1[i][j];
NOW1[0] = A1[i][j];
NOW2[0] = A2[i][j];
VIS[i][j] = true;
dfs(i, j, 1);
VIS[i][j] = false;
if (FLAG) {
X1 = i, Y1 = j;
return;
}
}
}
}
int main()
{
int n, t;
sc("%d", &n);
N = n;
a[1][1] = 1;
a[1][2] = 0;
a[n][n] = 0;
printf("? %d %d %d %d\n", 1, 2, 2, 3);
fflush(stdout);
scanf("%d", &t);
if (t == 1)
a[2][3] = a[1][2];
else
a[2][3] = a[1][2] ^ 1;
printf("? %d %d %d %d\n", 2, 1, 2, 3);
fflush(stdout);
scanf("%d", &t);
if (t == 1)
a[2][1] = a[2][3];
else
a[2][1] = a[2][3] ^ 1;
for (int i = 3; i <= n; i++)
{
printf("? %d %d %d %d\n", i - 2, 1, i, 1);
fflush(stdout);
scanf("%d", &t);
if (t == 1)
a[i][1] = a[i - 2][1];
else
a[i][1] = a[i - 2][1] ^ 1;
printf("? %d %d %d %d\n", 1, i - 2, 1, i);
fflush(stdout);
scanf("%d", &t);
if (t == 1)
a[1][i] = a[1][i - 2];
else
a[1][i] = a[1][i - 2] ^ 1;
}
for (int i = 2; i <= n; i++)
{
for (int j = 2; j <= n; j++)
{
if (i == j && j == n)
continue;
if (i == 2 && j == 3)
continue;
printf("? %d %d %d %d\n", i - 1, j - 1, i, j);
fflush(stdout);
scanf("%d", &t);
if (t == 1)
a[i][j] = a[i - 1][j - 1];
else
a[i][j] = a[i - 1][j - 1] ^ 1;
}
}
/*for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
printf("%d%c", a[i][j], j == n ? '\n' : ' ');
return 0;*/
solve();
printf("? %d %d %d %d\n", X1, Y1, X2, Y2);
fflush(stdout);
scanf("%d", &t);
printf("!\n");
if (t == 1)
{
if (color == 1)//不是
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if ((i + j) % 2 == 1)
printf("%d", a[i][j] ^ 1);
else
printf("%d", a[i][j]);
}
printf("\n");
}
}
else
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
printf("%d", a[i][j]);
printf("\n");
}
}
}
else
{
if (color == 2)//是
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if ((i + j) % 2 == 1)
printf("%d", a[i][j] ^ 1);
else
printf("%d", a[i][j]);
}
printf("\n");
}
}
else
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
printf("%d", a[i][j]);
printf("\n");
}
}
}
}
/*
3
0
0
0
0
0
1
101
110
010
*/
两个操作,操作一,给定下标元素加上一个值,操作二,求
分块,预处理所有操作二的模数小于 的,直接输出答案,对于模数大于的,暴力求出答案,复杂度 ,然后对于每一个操作一,我们只维护模数小于的,复杂度也是,总体复杂度
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
ll s[715][715];
ll a[500005];
int main()
{
int T;
sc("%d", &T);
while (T--)
{
int op, l, r;
sc("%d%d%d", &op, &l, &r);
if (op == 1)
{
for (int i = 1; i <= 710; i++)
s[i][l % i] += r;
a[l] += r;
}
else
{
ll ans = 0;
if (l > 710)
{
for (int i = r; i <= 500000; i += l)
ans += a[i];
}
else
{
ans = s[l][r];
}
printf("%lld\n", ans);
}
}
}