联合省选2021题解
突然发现500+好像挺容易的,有手就行
然而比赛的时候连400都没有
直接开始吧
卡牌游戏
https://www.luogu.com.cn/problem/P7514
瞎**贪心就完了,二分一手
code:
#include<bits/stdc++.h>
#define N 2000050
using namespace std;
int n, m, a[N], b[N], qma[N], qmi[N], mii[N], bb[N];
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++) scanf("%d", &b[i]), bb[i] = max(bb[i - 1], b[i]);
//sort(c + 1, c + 1 + sz);
int ans = a[n] - a[1];
m = min(n, m);
//qma[m] = a[m];
int mi = b[n], ma = b[n];
for(int i = n; i >= n - m + 1; i --) {
if(a[i] <= b[i]) break;
mi = min(mi, b[i]), ma = max(ma, b[i]);
int pos = m - (n - i + 1);
qma[pos] = max(ma, a[i - 1]); qmi[pos] = mi;
int maa = max(qma[pos], a[1]), mii = min(qmi[pos], a[1]);
ans = min(ans, maa - mii);
}
qma[m] = qmi[m] = a[n];
mi = b[1];
for(int i = 1; i < n; i ++) {
mi = min(b[i], mi);
mii[i] = min(mi, a[i + 1]);
}
for(int i = 1; i < n; i ++) mii[i] = max(mii[i], mii[i - 1]);
for(int i = 1; i <= n; i ++) if(qma[i]){
// printf("%d %d\n", qma[i], qmi[i]);
int pos = lower_bound(bb + 1, bb + 1 + n, qma[i]) - bb - 1;
pos = min(pos, i);
mi = min(mii[pos], qmi[i]), ma = qma[i];
// printf(" %d %d %d %d\n", ma, mi, pos, i);
ans = min(ans, ma - mi);
}
sort(b + 1, b + 1 + n);
ans = min(ans, b[n] - b[1]);
printf("%d", ans);
return 0;
}
矩阵游戏
https://www.luogu.com.cn/problem/P7515
先乱搞出一个不考虑1000000限制的a数组
发现对于a的一行的所有数依次+1,-1,+1,-1,… b数组并不会变
对列同理
假设对第
i
i
i行加上的值为
r
[
i
]
r[i]
r[i],列为
c
[
i
]
c[i]
c[i]
显然增加的矩阵可以写成
r
[
1
]
+
c
[
1
]
−
r
[
1
]
+
c
[
2
]
r
[
1
]
+
c
[
3
]
r
[
2
]
−
c
[
1
]
−
r
[
2
]
−
c
[
2
]
r
[
2
]
−
c
[
3
]
r
[
3
]
+
c
[
1
]
−
r
[
3
]
+
c
[
2
]
r
[
3
]
+
c
[
3
]
\begin{matrix} r[1]+c[1] & -r[1]+c[2]& r[1]+c[3] \\ r[2]-c[1] & -r[2]-c[2]& r[2]-c[3] \\ r[3]+c[1] & -r[3]+c[2]& r[3]+c[3] \end{matrix}
r[1]+c[1]r[2]−c[1]r[3]+c[1]−r[1]+c[2]−r[2]−c[2]−r[3]+c[2]r[1]+c[3]r[2]−c[3]r[3]+c[3]
假设上面的为
C
C
C
即要满足
0
<
=
A
i
,
j
+
C
i
,
j
<
=
1
0
6
0<=A_{i,j}+C_{i,j}<=10^6
0<=Ai,j+Ci,j<=106
移项
−
A
i
,
j
<
=
C
i
,
j
<
=
1
0
6
−
A
i
,
j
-A_{i,j}<=C_{i,j}<=10^6-A_{i,j}
−Ai,j<=Ci,j<=106−Ai,j
显然是个差分约束
但是上面那个矩阵有和又有差的不太好搞
发现两个都是+或者两个都是-的都是
(
i
+
j
)
m
o
d
2
=
=
0
(i+j) mod 2 == 0
(i+j)mod2==0的,对于这种把其中一个取反即可,我貌似是钦定
c
j
c_{j}
cj为负
因为关系的是绝对值的大小,而不是具体的正负,但是同一行(或列)一定要同一
具体看代码吧
code:
#include<bits/stdc++.h>
#define N 605
#define ll long long
using namespace std;
const ll INF = (1e18);
ll g[N][N];
void insert(int u, int v, int c) {
g[u][v] = c;
}
int in[N], vis[N], n, m;
ll dis[N];
queue<int> q;
int ok() {
for(int i = 0; i <= n + m; i ++) vis[i] = 0, in[i] = 0, dis[i] = INF;
while(q.size()) q.pop();
dis[1] = 0; q.push(1);
while(q.size()) {
int u = q.front(); q.pop();
vis[u] = 0;
if(in[u] > n + m) return 0;
for(int v = 1; v <= n + m; v ++) if(g[u][v] != INF){ ll c = g[u][v];
if(dis[u] + c < dis[v]) {
dis[v] = dis[u] + c; ++ in[v];
if(!vis[v]) {
vis[v] = 1; q.push(v);
}
}
}
}
return 1;
}
int a[N][N], b[N][N];
const int MX = 1000000;
void solve() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n + m; i ++)
for(int j = 1; j <= n + m; j ++) g[i][j] = INF;
for(int i = 1; i < n; i ++)
for(int j = 1; j < m; j ++) scanf("%d", &b[i][j]);
for(int i = n; i >= 1; i --)
for(int j = m; j >= 1; j --) a[i][j] = b[i][j] - a[i + 1][j] - a[i][j + 1] - a[i + 1][j + 1];
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++) {
if((i + j) & 1) {
insert(i, j + n, a[i][j]);
insert(j + n, i, MX - a[i][j]);
} else {
insert(i, j + n, MX - a[i][j]);
insert(j + n, i, a[i][j]);
}
}
/* for(int i = 1; i <= n + m; i ++) {
for(int j = 1; j <= n + m; j ++) printf(" %d ", g[i][j]); printf("\n");
}*/
if(!ok()) { printf("NO\n"); return ;}
else {
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++) {
if((i + j) & 1) a[i][j] += dis[i] - dis[j + n];
else a[i][j] += dis[j + n] - dis[i];
}
printf("YES\n");
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) printf("%d ", a[i][j]); printf("\n");
}
}
}
int t;
int main() {
scanf("%d", &t);
while(t --) solve();
return 0;
}
图函数
https://www.luogu.com.cn/problem/P7516
这题代码竟然是最短的!!!
宝石
https://www.luogu.com.cn/problem/P7518
就分成从下往上和从下往上两种情况,然后拼起来
无脑做,应该是不难的,就是写起来有点烦
code:
#include<bits/stdc++.h>
#define N 400005
using namespace std;
struct edge {
int v, nxt;
} e[N << 1];
int p[N], eid;
void init() {
memset(p, -1, sizeof p);
eid = 0;
}
void insert(int u, int v) {
e[eid].v = v;
e[eid].nxt = p[u];
p[u] = eid ++;
}
int dep[N], fa[N][20], f[N][20], g[N][20], ff[N], a[N], b[N], cc[N], col[N], cid[N], ans[N];
int n, m, c, qq;
struct Q {
int x, id, qi;
};
vector<Q> q[N];
void dfs(int u) { //if(u == 64904) printf("%d ", u);
dep[u] = dep[fa[u][0]] + 1;
ff[u] = ff[fa[u][0]];
int id = cid[col[u]];
if(id) {
// printf(" %d %d\n", u, id);
if(id == 1) ff[u] = u;
if(a[id + 1]) f[u][0] = a[id + 1];
if(a[id - 1]) g[u][0] = a[id - 1];
swap(a[id], b[u]);
}
//for(int i = 1; i <= 10; i ++) printf("%d ", a[i]); printf("\n");
for(int i = p[u]; i + 1; i = e[i].nxt) { //if(u == 64904) printf("*%d*", i);
int v = e[i].v;
if(v == fa[u][0]) continue;
fa[v][0] = u;
//if(u == 64904) printf("*%d*", v), dfs(v);
dfs(v);
}
if(id) {
swap(a[id], b[u]);
}
}
int check(int x, int y, int z) {
x = a[x];
if(!x) return 0;
for(int i = 0; i <= 18; i ++) {
if((z >> i) & 1) x = g[x][i];
if(dep[x] < dep[y]) return 0;
}
return dep[x] >= dep[y];
}
void dfss(int u) {
int id = cid[col[u]];
if(id) swap(a[id], b[u]);
/* if(u == 5) {
for(int i = 1; i <= m; i ++) printf(" %d ", a[i]); printf("\n");
}*/
for(int i = 0; i < q[u].size(); i ++) {
int x = q[u][i].x, id = q[u][i].id, qi = q[u][i].qi;
int l = 0, r = c - qi + 2;
while(l + 1 < r) {
int mid = (l + r) >> 1;
if(check(qi + mid - 1, x, mid - 1)) l = mid;
else r = mid;
}// printf("^%d %d %d %d %d %d %d^\n", id, l, qi + l - 1, x, l - 1, a[qi + l - 1], g[a[qi + l - 1]][0]);
ans[id] += l;
}
for(int i = p[u]; i + 1; i = e[i].nxt) {
int v = e[i].v;
if(v == fa[u][0]) continue;
dfss(v);
}
if(id) {
swap(a[id], b[u]);
}
}
int LCA(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = 18; i >= 0; i --) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if(x == y) return x;
for(int i = 18; i >= 0; i --) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int main() {
// freopen("gem.in","r",stdin);
// freopen("gem.out","w",stdout);
init();
scanf("%d%d%d", &n, &m, &c);
for(int i = 1; i <= c; i ++) scanf("%d", &cc[i]), cid[cc[i]] = i;
for(int i = 1; i <= n; i ++) scanf("%d", &col[i]), b[i] = i;
for(int i = 1; i < n; i ++) {
int u, v;
scanf("%d%d", &u, &v);
insert(u, v), insert(v, u);
}
dfs(1);
for(int j = 1; j <= 18; j ++)
for(int i = 1; i <= n; i ++)
fa[i][j] = fa[fa[i][j - 1]][j - 1],
f[i][j] = f[f[i][j - 1]][j - 1],
g[i][j] = g[g[i][j - 1]][j - 1];
/* for(int j = 0; j <= 5; j ++) {
for(int i = 1; i <= n; i ++) printf("%d ", g[i][j]); printf("\n");
}*/
scanf("%d", &qq);
for(int t = 1; t <= qq; t ++) {
int u, v;
scanf("%d%d", &u, &v);
int lca = LCA(u, v);
// printf("%d %d %d\n", u, v, lca);
if(lca == v) {
int x = ff[u];
if(dep[x] >= dep[lca]) {
for(int i = 18; i >= 0; i --) if(dep[f[x][i]] >= dep[lca]) x = f[x][i];
ans[t] = cid[col[x]];
} else ans[t] = 0;
//printf("*%d*", t);
} else
if(lca == u) {
Q ha;
ha.x = lca; ha.id = t, ha.qi = 1;
q[v].push_back(ha);
} else {
int x = ff[u];
if(dep[x] >= dep[lca]) {
for(int i = 18; i >= 0; i --) if(dep[f[x][i]] >= dep[lca]) x = f[x][i];
Q ha;
ha.x = lca; ha.id = t, ha.qi = cid[col[x]] + 1;
ans[t] = ha.qi - 1;
if(ha.qi <= c) q[v].push_back(ha);
} else {
Q ha;
// printf("*%d %d %d %d*\n", v, lca, t, 1);
ha.x = lca; ha.id = t, ha.qi = 1;
q[v].push_back(ha);
}
}
}
for(int i = 0; i <= n; i ++) b[i] = i, a[b[i]] = 0;
dfss(1);
for(int i = 1; i <= qq; i ++) printf("%d\n", ans[i]);
return 0;
}
to be continue……