当前位置: 首页 > news >正文

20251108OIFHA

T1

赛时未考虑到最大值不能取模,饮恨败北了...

直接顺着题目思路往下想就可以了.

首先考虑询问求的是两个弱连通分量(忽略边的方向的连通块)之间连边,再求最长路径的期望.容易把问题转化成预处理出以这个点为起点的最长路径长度\(dis[x]\)和以这个点为终点的最长路径长度\(en[x]\),再遍历两个弱连通分量内的所有点\(x\),\(y\),再求\(\sum_{x} \sum_{y} min(原最大值,en[x]+dis[y])\),但这样做的时间复杂度为\(O(qn^2)\),但看到有\(min\)操作,于是可以用双指针优化或二分优化(具体见代码).

那么难点在于如何求出\(en[x]\)\(dis[x]\).由于一个强连通分量内的点可以相互到达且可以重复走同一条边,那么一个点先走完它所属的强连通分量一定不劣.于是先缩点得到一个\(DAG\),即可得到\(en[x]\).建反图再做拓扑排序即可得到\(dis[x]\).而原最大值即为\(Max_{dis[x]}\).

注意空间只有16mib,是"Impossib1e."不是"Impossible.",求最大值过程中不能
取模.

代码如下(用双指针还是比二分要快的):

#include <bits/stdc++.h>
using namespace std;
#define int long longint n, m;
const int mod = 100000007;
int qpow(int xx, int yy) {long long ans = 1ll, x = xx, y = yy;while (y) {if (y % 2ll == 1ll) {ans *= x;ans %= mod;}y /= 2;x *= x;x %= mod;}return ans;
}
struct QQ {int x, y, val, id, v;
} Q[3600];
bool cmp(int x, int y) { return x > y; }
struct E1 {int v, nxt, to;
} e[55000], e2[55000], E[155000];
struct EC {int x, y, v;bool operator<(const EC &h) const {if (x == h.x) {if (y == h.y) {return v > h.v;}return y < h.y;}return x < h.x;}bool operator==(const EC &h) const { return (x == h.x) && (y == h.y); }
} E1[155000];
int t1, t2;
int head[3600], cnt;
int head2[3600], cnt2;
int Head[3600], Cnt;
void add(int x, int y, int v) {cnt++;e[cnt].to = y;e[cnt].v = v;e[cnt].nxt = head[x];head[x] = cnt;
}
void add3(int x, int y, int v) {cnt2++;e2[cnt2].to = y;e2[cnt2].v = v;e2[cnt2].nxt = head2[x];head2[x] = cnt2;
}
void add2(int x, int y, int v) {Cnt++;E[Cnt].to = y;E[Cnt].v = v;E[Cnt].nxt = Head[x];Head[x] = Cnt;
}
int col[3600], dfn[3600], low[3600], st[3600], tmp, kind;
int v[3600], dis[3600], en[3600];
deque<int> q;
// e
void dfs(int x) {dfn[x] = low[x] = ++tmp;st[x] = 1;q.push_back(x);for (int i = head[x]; i; i = e[i].nxt) {int to = e[i].to;if (!dfn[to]) {dfs(to);low[x] = min(low[x], low[to]);} else if (st[to]) {low[x] = min(low[x], dfn[to]);}}if (dfn[x] == low[x]) {++kind;while (!q.empty()) {int t = q.back();q.pop_back();st[t] = 0;col[t] = kind;if (t == x) {break;}}}
}
// e2
int ru[3600];
queue<int> d;
void tp1() {while (!d.empty()) d.pop();for (int i = 1; i <= kind; i++) {if (ru[i] == 0)d.push(i);}while (!d.empty()) {int tp = d.front();d.pop();for (int i = head2[tp]; i; i = e2[i].nxt) {int to = e2[i].to;en[to] = max(en[to], en[tp] + e2[i].v + v[tp]);ru[to]--;if (!ru[to])d.push(to);}}
}
void tp2() {while (!d.empty()) d.pop();for (int i = 1; i <= kind; i++) {if (ru[i] == 0)d.push(i);}while (!d.empty()) {int tp = d.front();d.pop();for (int i = head2[tp]; i; i = e2[i].nxt) {int to = e2[i].to;dis[to] = max(dis[to], dis[tp] + e2[i].v + v[tp]);ru[to]--;if (!ru[to])d.push(to);}}
}
int vis[3600], op;
vector<int> s[3600][2];
// E
void li(int x) {vis[x] = op;s[op][0].push_back(en[col[x]]);s[op][1].push_back(dis[col[x]]);for (int i = Head[x]; i; i = E[i].nxt) {int to = E[i].to;if (!vis[to]) {li(to);}}
}
int an = 0;
int query(int x, int y, int va) {int sx = s[x][0].size() - 1, sy = s[y][1].size() - 1;int num = ((sx + 1) * (sy + 1)) % mod, t = 0, sum = 0, su = 0;for (int i = 0; i <= sx; i++) {while (s[y][1][t] + s[x][0][i] + va > an && t <= sy) {su += s[y][1][t];su %= mod;t++;}if (t == sy && s[y][1][t] + s[x][0][i] + va > an) {sum += (su + ((sy + 1) * (s[x][0][i] + va) % mod) % mod) % mod;} else {sum += ((sy - t + 1) * (an % mod)) % mod + (su + (t * (s[x][0][i] + va) % mod) % mod) % mod;}sum %= mod;}return sum * qpow(num, mod - 2) % mod;
}
void init() {// edgecnt = cnt2 = Cnt = 0;memset(head, 0, sizeof(head));memset(head2, 0, sizeof(head2));memset(Head, 0, sizeof(Head));// othertmp = 0, kind = 0, op = 0, an = 0, t1 = 0;memset(col, 0, sizeof(col));memset(dfn, 0, sizeof(dfn));memset(low, 0, sizeof(low));memset(st, 0, sizeof(st));memset(v, 0, sizeof(v));memset(dis, 0, sizeof(dis));memset(en, 0, sizeof(en));memset(vis, 0, sizeof(vis));for (int i = 1; i <= 3000; i++) s[i][0].clear(), s[i][1].clear();while (!q.empty()) q.pop_front();
}
void sol() {scanf("%lld%lld", &n, &m);init();for (int i = 1; i <= m; i++) {int x, y, v;scanf("%lld%lld%lld", &x, &y, &v);add(x, y, v);add2(x, y, v);add2(y, x, v);}for (int i = 1; i <= n; i++) {if (!dfn[i]) {dfs(i);}}for (int i = 1; i <= n; i++) {for (int j = head[i]; j; j = e[j].nxt) {int to = e[j].to;if (col[to] != col[i]) {E1[++t1] = { col[i], col[to], e[j].v };} else {v[col[i]] += e[j].v;}}}sort(E1 + 1, E1 + 1 + t1);memset(head2, 0, sizeof(head2));memset(ru, 0, sizeof(ru));cnt2 = 0;for (int i = 1; i <= t1; i++) {if (E1[i] == E1[i - 1])continue;ru[E1[i].y]++;add3(E1[i].x, E1[i].y, E1[i].v);}tp1();memset(ru, 0, sizeof(ru));memset(head2, 0, sizeof(head2));cnt2 = 0;for (int i = 1; i <= t1; i++) {if (E1[i] == E1[i - 1])continue;ru[E1[i].x]++;add3(E1[i].y, E1[i].x, E1[i].v);}tp2();for (int i = 1; i <= kind; i++) {dis[i] += v[i], en[i] += v[i];an = max(an, dis[i]);}for (int i = 1; i <= n; i++) {if (!vis[i]) {op++;li(i);}}for (int i = 1; i <= op; i++) {sort(s[i][0].begin(), s[i][0].end());sort(s[i][1].begin(), s[i][1].end(), cmp);}int qnum;scanf("%lld", &qnum);for (int i = 1; i <= qnum; i++) {int x, y, v;scanf("%lld%lld%lld", &x, &y, &v);if (vis[x] == vis[y]) {printf("Impossib1e.\n");continue;}printf("%lld\n", query(vis[x], vis[y], v));}
}
signed main() {int T;scanf("%lld", &T);while (T--) {sol();}
}

T2

先观察变化规律.容易发现KXP将P放到开头就变成了PKX,再把X放到开头就变成了XPK。由此可以得出它们是循环变换的。那么这就有一个很好的的性质:我们设KXP,PKX,XPK为"*** "(因为它们可以互相转换,所以具体是什么不重要),那么*** K/P/X可以变为K/P/X***(可以自行枚举证明)。

解决字符串匹配有两种常见方法,一是从左往右让\(S\)\(T\)一一匹配,匹配完成的部分不去管它。另一种是若操作可逆,则将\(S\)\(T\)变为同一个字符串,即可证明两个字符串是匹配的。

本题用方法一不好处理。注意到操作可逆,且有开头提到的性质,于是思考方法二。我们可以发现,只有*** 是可以随便动的,那我们让所有*** 移到后面,在比较\(S\)\(T\)剩余不可移动部分是否相等,即可得到是否匹配。

那么如何把所有*** 求出来呢?(记得考虑一个*** 移走后两边有可能可以重新拼成一个 *** )。由于*** 长度只有3,那么一种优秀的写法是用栈来维护,从左往右枚举,每次遇到一个数,看一下它和栈顶两个字符能否拼成***,如果可以就把它们弹出栈,否则压入当前字符。

代买实现较为简单,就不贴了。

T3

太菜了

T4

太菜了

http://www.zskr.cn/news/46873.html

相关文章:

  • Python serialize listT
  • 指数生成函数
  • 基于SpringBoot+Vue的线上一流课程教学辅助系统管理系统设计与实现【Java+MySQL+MyBatis完整源码】 - 指南
  • 类 类型转化(运用子类的方法)
  • 11/11
  • 重大收获的一天
  • 关于做过的第一道实验题的思考
  • #20232329 2025-2026-1 《网络与系统攻防技术》 实验五实验报告
  • 2025 年 11 月深圳龙岗网站建设厂家推荐排行榜,外贸独立站推广,阿里巴巴/1688店铺代运营,短视频拍摄运营,商标注册,小程序开发公司精选
  • 2025 年 11 月财税合规服务厂家推荐排行榜,电商/跨境电商/出口退税/公司注销/股权设计/平台报送/亚马逊/Temu/速卖通/高新企业/审计报告全案解决方案
  • Appium Inspector教程
  • pythontip 映射字符串中的字母
  • 什么是glTF,与glb的区别,规格和优点,通俗易懂地解释下载获取
  • 算法训练之BFS解决最短路径难题
  • 电商运营每天在忙啥?拆解4个核心工作,新手也能照做 - 智慧园区
  • 论安慰人
  • 102302112王光诚作业2
  • ff
  • 深入解析:嵌入式软件架构--按键消息队列2(组合键,按键转义与三种消息模式)
  • 2025优质弯管厂家推荐榜:合肥翼达机械五星领跑,安徽企业助力产业升级
  • Redisson源码剖析-可重试机制的实现
  • 2025浸没式/液冷超充/新能源车/超充站领域实力厂家排行榜:中碳创新领衔,四大品牌重塑新能源车补能生态
  • 2025国内AI获客公司排行榜:全平台精准破局,4 家企业领跑抖音/快手/小红书获客赛道
  • HNOI2016 序列
  • 2025年山东画室机构实力推荐:济南大道画室领跑美术艺考培训新标准
  • 第三十八篇
  • 英语_阅读_The progress of technology_待读
  • 机动车登记证识别技术如何通过深度学习实现泛化能力提升
  • 深入解析:51单片机基础-矩阵按键
  • gmssl 国密标准下载