2022.11.20
坐在这里就开始困。
去洛谷上报了个比赛,四个题都戳了戳,都不大会,暴力也写的很丑,于是乖乖回去复习我的知识点。
$ $
为了一首歌下了一个软件,然后这首歌要收费!!!
果断卸载,咱不听了。
$ $
中午睡了不到一个小时,没睡醒。
考试……
考试的时间过得好快啊!
挺划的。
%%% ZXS
冒泡排序
神奇的 memset。
知道 memset 的常数大,没想这么大。
/*
Date:
Source:
knowledge:
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#define orz cout << "AK IOI" << "\n";
using namespace std;
const int maxn = 1e6 + 10;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
int T, n, a[maxn], sum[maxn];
int main()
{
// freopen("bubble.in", "r", stdin);
// freopen("bubble.out", "w", stdout);
T = read();
while(T--)
{
n = read();
for(int i = 1; i <= n; i++) sum[i] = 0;
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= n; i++)
{
if (i == a[i]) continue;
int l = Min(i, a[i]), r = Max(i, a[i]);
sum[l]++, sum[r + 1]--;
}
for(int i = 1; i <= n; i++) sum[i] += sum[i - 1];
int ans = 0;
for(int i = 1; i <= n; i++) if(sum[i]) ans++;
printf("%d\n", ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}
异或国度
40 pts, 思路也很朴素,求出任何两点之间的距离。
其实考场思路已经是 60 pts 了。
但是wa 了两点,调了调wa了另外俩点。
/*
Date:2022.11.20
Source:模拟赛
knowledge:树上差分吗 调半天一个sb错误
没有可供调试的小样例
*/
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define orz cout << "AK IOI" << "\n";
using namespace std;
const int maxn = 5e5 + 10;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
int n, q, w[maxn], dis[1010][1010];
struct node{
int u, v, nxt;
}e[1000010 << 1];
int js, head[maxn];
void add(int u, int v)
{
e[++js] = (node){u, v, head[u]};
head[u] = js;
}
void dfs(int u, int fa, int top)
{
for(int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(v == fa) continue;
dis[top][v] = dis[top][u] ^ w[v];
dfs(v, u, top);
}
}
int main()
{
n = read(), q = read();
for(int i = 1; i <= n; i++) w[i] = read();
for(int i = 1; i <= n - 1; i++)
{
int u = read(), v = read();
add(u, v), add(v, u);
}
for(int i = 1; i <= n; i++) dis[i][i] = w[i], dfs(i, 0, i);
for(int i = 1; i <= q; i++)
{
int u = read(), v = read(), k = read(), flag = 0;
for(int j = 1; j <= n; j++)
{
if(j == u || j == v) continue;
if((dis[u][j] ^ dis[j][v]) == k)
{
puts("Yes"); flag = 1;
break;
}
}
if(flag == 0) puts("No");
}
fclose(stdin);
fclose(stdout);
return 0;
}
简单的写一写吧
u 到 x 和 u到 y 路径的公共部分会异或两遍,所以这两条路的权值的异或和其实是 \(s_{u, x}\) ^ \(s_{u, y}\) ^ \(w_z\) = \(k\) ,移项 \(s_{u, x}\) ^$ s_{u, y}$ ^ $k = w_z $
那么就将问题转换成了是否存在点 \(z\) 使该式子成立。
$ $
!没明白, 不会写,不改了!
青岛地铁
爆搜 35 pts 有锅,懒得调了。
/*
Date:2022.11.20
Source:模拟赛
knowledge:
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#define int long long
#define orz cout << "AK IOI" << "\n";
using namespace std;
const int maxn = 15;
const int maxm = 1e5 + 10;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
int n, m, ans, a[maxn][maxm], c[maxn], u[maxn][maxm], num[maxn];
signed main()
{
//freopen("metro.in", "r", stdin);
//freopen("metro.out", "w", stdout);
n = read(), m = read();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) a[i][j] = read();
for(int i = 1; i <= n; i++)
{
c[i] = read();
for(int j = 1; j <= c[i]; j++) u[i][j] = read();
}
for(int i = 1; i <= n; i++) num[i] = i;
int ans = 1e18, res = 0;
for(int i = 1; i <= n; i++) //线路
{
for(int j = 1; j <= c[i]; j++) res += a[num[i]][u[i][j]];
}
ans = Min(ans, res);
while(next_permutation(num + 1, num + n + 1))
{
res = 0;
for(int i = 1; i <= n; i++) //线路
{
for(int j = 1; j <= c[i]; j++) res += a[num[i]][u[i][j]];
}
ans = Min(ans, res);
}
print(ans);
fclose(stdin);
fclose(stdout);
return 0;
}
/*
1 3
4 1 5
2 1 2
*/
根据数据范围能看出来用状压。
我不会,跑路了。
数列问题
50pts 朴素的暴力
/*
Date:2022.11.20
Source:模拟赛
knowledge: 先码的线段树,发现有错,而且调不出来
so,区间最值为什么不用st 表
*/
#include <cstdio>
#include <iostream>
#define orz cout << "AK IOI" << "\n";
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
const int maxn = 1e6 + 10;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
int n, ans, a[maxn], mp[6010][6010];
int st[maxn][21], st2[maxn][21], lg[maxn];
void init()
{
for(int i = 1; i <= n; i++) lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
}
void ST()
{
for(int j = 1; j <= 20; j++)
{
for(int i = 1; i + (1 << j) - 1 <= n; i++)
st[i][j] = Max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
}
for(int j = 1; j <= 20; j++)
{
for(int i = 1; i + (1 << j) - 1 <= n; i++)
st2[i][j] = Min(st2[i][j - 1], st2[i + (1 << (j - 1))][j - 1]);
}
}
int query_Max(int l, int r)
{
int k = lg[r - l + 1] - 1;
return Max(st[l][k], st[r - (1 << k) + 1][k]);
}
int query_Min(int l, int r)
{
int k = lg[r - l + 1] - 1;
return Min(st2[l][k], st2[r - (1 << k) + 1][k]);
}
int main()
{
n = read();
for(int i = 1; i <= n; i++) a[i] = read(), st[i][0] = st2[i][0] = a[i];
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++) mp[a[j]][i] = mp[a[j]][i - 1];
mp[a[i]][i] = mp[a[i]][i - 1] + 1;
}
init(), ST();
for(int l = 1; l <= n; l++)
{
for(int r = l; r <= n; r++)
{
int maxx = query_Max(l, r), minn = query_Min(l, r), flag = 0;
if((maxx + minn) * (maxx - minn + 1) / 2 != (r - l + 1)) continue;
for(int i = minn; i <= maxx; i++)
if(mp[i][r] - mp[i][l - 1] != i) flag = 1;
if(flag == 0) ans++;
}
}
print(ans);
fclose(stdin);
fclose(stdout);
return 0;
}
这是有多想不开搁着补题!
摆!