【LOJ】#2270. 「SDOI2017」天才黑客
题解
显然要记录每个点来的状态,这样会扩充出点度的平方条边,就gg了
删掉所有的点,把每个边拆成两个点,连一条边权为c
这个时候我们考虑对于原先的每个点,将所有与其相连边所需要的节点(不管是进入还是出去)建一棵虚树,然后用线段树优化建图,优化方法是枚举每个lca,然后将lca的每个子树和其他子树连一条长度为lca深度的边,也就是dfs序上连续的一段
进到这个点的边拆出来的点和负责出去的线段树的子节点连一条边
负责进来的线段树向这个点出去的节点连一条边
跑最短路就行
然后就做完了……
写的我真累= =
我非常好奇到底如何能只写3.xK????
update:貌似有更清奇的写法不用线段树orzzzzz
代码
(7.6K的sd代码,不看也罢)
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
#define MAXN 200005
#define MAXK 80005
typedef long long int64;
using namespace std;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,M,K;
priority_queue<pair<int64,int> > Q;
namespace Tree {
struct node {
int next,to;
}E[MAXK * 2];
int head[MAXK],sumE,dfn[MAXK],idx,dep[MAXK];
int st[MAXK * 2][17],len[MAXK * 2],pos[MAXK],tot;
void add(int u,int v) {
E[++sumE].next = head[u];
E[sumE].to = v;
head[u] = sumE;
}
int min_dep(int a,int b) {
return dep[a] < dep[b] ? a : b;
}
int lca(int a,int b) {
a = pos[a];b = pos[b];
if(a > b) swap(a,b);
int l = len[b - a + 1];
return min_dep(st[a][l],st[b - (1 << l) + 1][l]);
}
void dfs(int u,int fa) {
dfn[u] = ++idx;
st[++tot][0] = u;pos[u] = tot;dep[u] = dep[fa] + 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa) {
dfs(v,u);
st[++tot][0] = u;
}
}
}
void Init() {
sumE = 0;memset(head,0,sizeof(head));idx = 0;
memset(st,0,sizeof(st));
int u,v,w;
for(int i = 1 ; i < K ; ++i) {
read(u);read(v);read(w);
add(u,v);
}
idx = 0;tot = 0;
dfs(1,0);
for(int i = 2 ; i <= tot ; ++i) len[i] = len[i / 2] + 1;
for(int j = 1 ; j <= 16 ; ++j) {
for(int i = 1 ; i <= tot ; ++i) {
st[i][j] = min_dep(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);
}
}
}
}
namespace Graph {
struct node {
int next,to;
int64 val;
}E[4000005];
int head[1000005],sumE,pos[1000005],Ncnt,S;
vector<int> vec[MAXN][2];
int Line[200005],tot,sta[MAXK],top,faAux[MAXK],siz[MAXK],d[MAXK],pz[2][MAXK],tr[2][MAXK * 8];
int64 dis[1000005];
bool vis[1000005];
bool cmp(int a,int b) {
return Tree::dfn[a] < Tree::dfn[b];
}
void add(int u,int v,int64 c) {
E[++sumE].to = v;
E[sumE].next = head[u];
E[sumE].val = c;
head[u] = sumE;
}
void Init() {
sumE = 0;Ncnt = 0;memset(head,0,sizeof(head));
for(int i = 1 ; i <= N ; ++i) {vec[i][0].clear();vec[i][1].clear();}
int a,b,d;
int64 c;
for(int i = 1 ; i <= M ; ++i) {
read(a);read(b);read(c);read(d);
pos[Ncnt + 1] = d;pos[Ncnt + 2] = d;
vec[a][1].pb(Ncnt + 1);vec[b][0].pb(Ncnt + 2);
add(Ncnt + 1,Ncnt + 2,c);
Ncnt += 2;
}
S = ++Ncnt;
pos[S] = 1;vec[1][0].pb(S);
}
void Build_SegmentTree(int id,int u,int L,int R) {
tr[id][u] = ++Ncnt;
if(L == R) {pz[id][Line[R]] = Ncnt;return;}
int mid = (L + R) >> 1;
Build_SegmentTree(id,u << 1,L,mid);
Build_SegmentTree(id,u << 1 | 1,mid + 1,R);
if(!id) {add(tr[id][u << 1],tr[id][u],0);add(tr[id][u << 1 | 1],tr[id][u],0);}
else {add(tr[id][u],tr[id][u << 1],0);add(tr[id][u],tr[id][u << 1 | 1],0);}
}
void Add_Edge(int id,int u,int L,int R,int l,int r,int v,int64 c) {
if(L == l && R == r) {
if(!id) {add(tr[id][u],v,c);}
else {add(v,tr[id][u],c);}
return;
}
int mid = (L + R) >> 1;
if(r <= mid) Add_Edge(id,u << 1,L,mid,l,r,v,c);
else if(l > mid) Add_Edge(id,u << 1 | 1,mid + 1,R,l,r,v,c);
else {Add_Edge(id,u << 1,L,mid,l,mid,v,c);Add_Edge(id,u << 1 | 1,mid + 1,R,mid + 1,r,v,c);}
}
void Build_AuxTree() {
top = 0;
sta[++top] = Line[1];faAux[Line[1]] = 0;
int c = tot;
for(int i = 2 ; i <= c ; ++i) {
int f = Tree::lca(sta[top],Line[i]);
while(top >= 1 && Tree::dep[sta[top]] > Tree::dep[f]) {
if(top == 1 || Tree::dep[sta[top - 1]] <= Tree::dep[f]) {
faAux[sta[top]] = f;
}
--top;
}
if(f != sta[top]) {
faAux[f] = sta[top];
sta[++top] = f;
Line[++tot] = f;
}
sta[++top] = Line[i];
faAux[Line[i]] = f;
}
sort(Line + 1,Line + tot + 1,cmp);
for(int i = 1 ; i <= tot ; ++i) siz[Line[i]] = 1;
for(int i = tot ; i >= 1 ; --i) {
siz[faAux[Line[i]]] += siz[Line[i]];
d[Line[i]] = i;
}
Build_SegmentTree(0,1,1,tot);
Build_SegmentTree(1,1,1,tot);
for(int i = 1 ; i <= tot ; ++i) {
int u = Line[i];
++Ncnt;
Add_Edge(0,1,1,tot,i,i,Ncnt,Tree::dep[u] - 1);
Add_Edge(1,1,1,tot,i,i + siz[u] - 1,Ncnt,0);
int f = faAux[u];
if(f) {
++Ncnt;
Add_Edge(0,1,1,tot,i,i + siz[u] - 1,Ncnt,Tree::dep[f] - 1);
if(d[f] <= i - 1)
Add_Edge(1,1,1,tot,d[f],i - 1,Ncnt,0);
if(d[f] + siz[f] - 1 >= i + siz[u])
Add_Edge(1,1,1,tot,i + siz[u],d[f] + siz[f] - 1,Ncnt,0);
}
}
}
void Build_Graph() {
for(int i = 1 ; i <= N ; ++i) {
tot = 0;
for(int k = 0 ; k <= 1 ; ++k) {
for(int j = 0 ; j < vec[i][k].size() ; ++j) {
Line[++tot] = pos[vec[i][k][j]];
}
}
sort(Line + 1,Line + tot + 1);
tot = unique(Line + 1,Line + tot + 1) - Line - 1;
sort(Line + 1,Line + tot + 1,cmp);
Build_AuxTree();
for(int k = 0 ; k <= 1 ; ++k) {
for(int j = 0 ; j < vec[i][k].size() ; ++j) {
int t = vec[i][k][j];
if(!k) add(t,pz[k][pos[t]],0);
else add(pz[k][pos[t]],t,0);
}
}
}
}
void Dijkstra() {
for(int i = 1 ; i <= Ncnt ; ++i) {
dis[i] = 1e16;vis[i] = 0;
}
dis[S] = 0;
Q.push(mp(-dis[S],S));
while(!Q.empty()) {
pair<int64,int> now = Q.top();Q.pop();
int u = now.se;
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u] ; i; i = E[i].next) {
int v = E[i].to;
if(dis[v] > dis[u] + E[i].val) {
dis[v] = dis[u] + E[i].val;
Q.push(mp(-dis[v],v));
}
}
}
}
void Print() {
for(int i = 2 ; i <= N ; ++i) {
int64 ans = 1e16;
for(int j = 0 ; j < vec[i][0].size() ; ++j) ans = min(ans,dis[vec[i][0][j]]);
out(ans);enter;
}
}
}
void Solve() {
read(N);read(M);read(K);
Graph::Init();
Tree::Init();
Graph::Build_Graph();
Graph::Dijkstra();
Graph::Print();
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int T;
read(T);
while(T--) Solve();
return 0;
}
md我zz吧
我代码是别人的两倍,运行时间也是别人的两倍啊
我附加点为什么最后都建到1000000去了,不应该啊,然后还0.5s?是LOJ的评测机扩充了我的想象力吗
好写???
没觉得好写啊???
我觉得刷新了我难写的上限啊???
思路和细节写的比NOI2018D2T2还累啊,我代码能力难道真的退化了???
【LOJ】#2270. 「SDOI2017」天才黑客的更多相关文章
- loj#2269. 「SDOI2017」切树游戏
还是loj的机子快啊... 普通的DP不难想到,设F[i][zt]为带上根玩出zt的方案数,G[i][zt]为子树中的方案数,后面是可以用FWT优化的 主要是复习了下动态DP #include< ...
- loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)
题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i ...
- @loj - 2004@ 「SDOI2017」硬币游戏
目录 @description@ @solution@ @accepted code@ @details@ @description@ 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数 ...
- LOJ #2005. 「SDOI2017」相关分析 线段树维护回归直线方程
题目描述 \(Frank\) 对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. \(Frank\) 不仅喜欢观测,还喜欢分析观测到的 ...
- [LOJ#2270][BZOJ4912][SDOI2017]天才黑客
[LOJ#2270][BZOJ4912][SDOI2017]天才黑客 试题描述 SD0062 号选手小 Q 同学为了偷到 SDOI7012 的试题,利用高超的黑客技术潜入了 SDOI 出题组的内联网的 ...
- LibreOJ 2003. 「SDOI2017」新生舞会 基础01分数规划 最大权匹配
#2003. 「SDOI2017」新生舞会 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
随机推荐
- 洛谷 P1852 [国家集训队]跳跳棋 解题报告
P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...
- Burpsuit分块传输插件绕WAF原理和技巧(转)
0x00 原理 给服务器发送payload数据包,使得waf无法识别出payload,当apache,tomcat等web容器能正常解析其内容.如图一所示 0x02 实验环境 本机win10+x ...
- 调试技巧 ------ printf 的使用技巧
编译器宏:__FUNCTION__,__FILE__,__LINE__ #define __debug #ifdef __debug //#define debug(format,...) print ...
- zabbix监控的基础概念、工作原理及架构(一)
zabbix监控的基础概念.工作原理及架构 转载于网络 一.什么是zabbix及优缺点 Zabbix能监视各种网络参数,保证服务器系统的安全运营,并提供灵活的通知机制以让系统管理员快速定位/解决存在的 ...
- Kubernetes Pod详解
目录 基本概念 pod资源配额 容器的健康检查 静态pod 基本概念 Pod是kubernetes集群中最基本的资源对象.每个pod由一个或多个业务容器和一个根容器(Pause容器)组成.Kubern ...
- bzoj千题计划290:bzoj3143: [Hnoi2013]游走
http://www.lydsy.com/JudgeOnline/problem.php?id=3143 计算每条边经过的概率e[] 然后经过概率多的分配的编号大,经过概率少的分配的编号小 如何计算边 ...
- bzoj千题计划176:bzoj1199: [HNOI2005]汤姆的游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=1199 求出圆x的范围 把要判断的点按x从小到大排序 枚举图形 二分出x满足这个图形的一段区间 枚举这 ...
- Github 开源项目(二) jsmpeg-vnc
参考文章:http://blog.csdn.net/qq_28877125/article/details/70141713 适用于Windows的低延迟,高帧率屏幕共享服务器以及用于浏览器的客户端 ...
- 网络基础知识(一)wireshark 三次握手实践
wireshark 三次握手简介 192.168.18.120 IP地址为我的本机虚拟机IP地址 过滤设置:ip.addr == 192.168.18.120 (ip.addr == 192.168. ...
- meeting,symposium,seminar 等区别
meeting,symposium,seminar 等区别 会议分类的方式可说是不胜枚举,这点初步由英文对会议名称的写法,就可看出端倪,像是Assembly,Caucus,Colloquium, Co ...