标签:rt typedef le int long 20220506 ql 模拟
20220506模拟赛
溜冰
题意
\(n\) 点 \(m\) 边,高度为 \(h_i\) ,若经过边\((u,v)\) 从 \(u\) 到 \(v\)
- \(h_u<h_v\) ,开心值减少 \(2(h_v-h_u)\)
- \(h_u>h_v\) ,开心值增加 \(h_u-h_v\)
- \(h_u=h_v\) ,开心值不便
初始在点 1 ,开心值为 0,求溜冰时最大开心值
\(n,m\le 2\times 10^5,h_i\le 10^8\)
无重边、自环
sol & code
直接连边跑 dijkstra ,有负权边,考虑转换
考虑将从起点到点 \(i\) 有固定开心值 \(h_1-h_i\) ,此处 \(h_1>h_i\) ,否则不是最优
则要到点 \(i\) 减少的开心值最少
若 \(h_u>h_v\) ,且经过中转点 \(k\) ,\(h_u<h_k\) ,即从 \(u\rightarrow k\rightarrow v\)
则最终开心值为 \(-2(h_k-h_u)+(h_k-h_v)=h_u-h_k+(h_u-h_v)\)
相比原来开心值,减少了 \(h_k-h_u\)
所以若 \(h_u<h_k\) ,连 \((u,k,h_k-h_u),(k,u,0)\) 两条边,反之同理。
跑最短路即可
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
typedef long double LD;
typedef long long LL;
typedef double db;
const int N = 200005;
int n, m, a[N], lst[N], Ecnt, vis[N];
LL dis[N], ans;
struct Ed { int to, nxt; LL qz; } e[N << 1];
inline void Ae(int fr, int go, int vl) {
e[++Ecnt] = (Ed){ go, lst[fr], 1ll * vl }, lst[fr] = Ecnt;
}
struct P {
int x; LL d;
bool operator < (P A) const {
return d > A.d;
}
} ;
priority_queue<P> Q;
inline void dij() {
for (int i = 1; i <= n; i++) dis[i] = 1e15;
dis[1] = 0, Q.push((P){ 1, 0 });
while (!Q.empty()) {
register int u = Q.top().x; Q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = lst[u], v; i; i = e[i].nxt)
if (dis[u] + e[i].qz < dis[v = e[i].to])
dis[v] = dis[u] + e[i].qz, Q.push((P){ v, dis[v] });
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
if (a[u] <= a[v]) Ae(u, v, a[v] - a[u]), Ae(v, u, 0);
if (a[u] > a[v]) Ae(u, v, 0), Ae(v, u, a[u] - a[v]);
}
dij();
for (int i = 2; i <= n; i++)
if (a[i] < a[1] && dis[i] < 1e15) ans = max(ans, a[1] - a[i] - dis[i]);
printf("%lld", ans);
}
满足条件的序列个数
题意 & sol
求满足以下条件的序列的个数,答案 \(\;mod\;998244353\)
- 序列的长度为 \(n\)
- 元素在 \([1,m]\) 之间
- 最长上升子序列长度刚好为 3
\(3\le n\le 1000, 3\le m\le 10\)
设 \(f_{i,k1,k2,k3}\) 表示前 \(i\) 个数,长度为 1 和 2 和 3 的最长上升子序列结尾的最小值为 \(k1,k2,k3\) 的方案
枚举 \(i\) 位选 \(j\)
- \(j\le k1\) ,\(f_{i,k1,k2,k3}\rightarrow f_{i+1,j,k2,k3}\)
- \(k1<j\le k2\) ,\(f_{i,k1,k2,k3}\rightarrow f_{i+1,k1,j,k3}\)
- \(k2<j\le k3\) ,\(f_{i,k1,k2,k3}\rightarrow f_{i+1,k1,k2,j}\)
\(f_{0,m+1,m+1,m+1}=1\)
code
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
typedef long double LD;
typedef long long LL;
typedef double db;
const LL P = 998244353;
int n, m;
LL f[1005][15][15][15], ans;
int main() {
scanf("%d%d", &n, &m);
f[0][m + 1][m + 1][m + 1] = 1;
for (int i = 0; i < n; i++)
for (int k1 = 1; k1 <= m + 1; k1++)
for (int k2 = k1; k2 <= m + 1; k2++)
for (int k3 = k2; k3 <= m + 1; k3++)
for (int j = 1; j <= m; j++) {
if (j <= k1) (f[i + 1][j][k2][k3] += f[i][k1][k2][k3]) %= P;
else if (j <= k2) (f[i + 1][k1][j][k3] += f[i][k1][k2][k3]) %= P;
else if (j <= k3) (f[i + 1][k1][k2][j] += f[i][k1][k2][k3]) %= P;
}
for (int i = 1; i <= m; i++)
for (int j = 1; j <= m; j++)
for (int k = 1; k <= m; k++)
(ans += f[n][i][j][k]) %= P;
printf("%lld", ans);
}
区间排序
题意 & sol
1 到 \(n\) 的排列 \(P\) 和整数 \(X\) ,\(Q\) 次操作对区间升序或降序排序。
求最后 X 的位置。
\(n\le 2*10^5\)
\(X\) 的位置只和排名有关,将 \(P\) 分为 \(\le X\) 和 \(>X\) 两类
可以先查询排名 \(rk\)
则升序排序可以转为 \([l,l+rk-1]\) 和 \([l+rk,r]\) 的区间修改操作
用线段树区间查询、修改,维护排名
code
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
typedef long double LD;
typedef long long LL;
typedef double db;
const int N = 200005, SQ = 450;
int n, Ti, X, a[N], pos, tg[N << 2], sm[N << 2], res;
#define ls (rt << 1)
#define rs (rt << 1 | 1)
inline void Up(int rt) {
sm[rt] = sm[ls] + sm[rs];
}
void bui(int l, int r, int rt) {
tg[rt] = -1;
if (l == r) { sm[rt] = a[l]; return; }
register int mid = l + r >> 1;
bui(l, mid, ls), bui(mid + 1, r, rs), Up(rt);
}
inline void down(int l, int r, int rt) {
if (tg[rt] == -1) return;
register int mid = l + r >> 1;
tg[ls] = tg[rt], sm[ls] = (mid - l + 1) * tg[rt];
tg[rs] = tg[rt], sm[rs] = (r - mid) * tg[rt];
tg[rt] = -1;
}
void ask(int ql, int qr, int l, int r, int rt) {
if (ql > r || l > qr) return;
if (ql <= l && r <= qr) { res += sm[rt]; return; }
register int mid = l + r >> 1; down(l, r, rt);
ask(ql, qr, l, mid, ls), ask(ql, qr, mid + 1, r, rs);
}
void mdy(int ql, int qr, int vl, int l, int r, int rt) {
if (ql > r || l > qr) return;
if (ql <= l && r <= qr) { tg[rt] = vl, sm[rt] = (r - l + 1) * vl; return; }
register int mid = l + r >> 1; down(l, r, rt);
mdy(ql, qr, vl, l, mid, ls);
mdy(ql, qr, vl, mid + 1, r, rs), Up(rt);
}
#undef ls
#undef rs
int main() {
scanf("%d%d%d", &n, &Ti, &X);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if (a[i] == X) pos = i;
a[i] = (a[i] <= X);
}
bui(1, n, 1);
for (int op, x, y; Ti--; ) {
scanf("%d%d%d", &op, &x, &y);
res = 0, ask(x, y, 1, n, 1);
if (op == 1) {
if (res) mdy(x, x + res - 1, 1, 1, n, 1);
mdy(x + res, y, 0, 1, n, 1);
if (x <= pos && pos <= y) pos = x + res - 1;
} else {
if (res) mdy(y - res + 1, y, 1, 1, n, 1);
mdy(x, y - res, 0, 1, n, 1);
if (x <= pos && pos <= y) pos = y - res + 1;
}
}
printf("%d", pos);
}
总结
- 最短路的转化,
dijkstra 不能跑负权(小声) - LIS 的状态表示
- 区间排序转化成排名
标签:rt,typedef,le,int,long,20220506,ql,模拟 来源: https://www.cnblogs.com/KonjakLAF/p/16243805.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。