《CF464E》 解题报告
时间:2023-08-26
本文章向大家介绍《CF464E》 解题报告,主要内容包括加法、比大小、使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
好题。
今天模拟赛出到这题的究极强化版,于是来写一下这题,也就是弱化版(你管这叫弱化版)
其实思路不难,但是比较有趣。
首先我们肯定是要维护这么一个高精的,但是如果直接维护肯定鉴定为寄。
考虑其他维护方法。
首先要知道 \(dij\) 是肯定不能少的。
我们思考 \(dij\) 主要有两个操作。
-
加法
-
比大小
也就是说如果我们可以在时间复杂度允许范围内做出这些操作,这题就做完了。
加法
考虑到所有边的权值都是 \(2^x\) 的特殊性。
我们考虑将他变成二进制进行维护。
而我们每走一条边就要在一位上加 \(1\)
这就导致了要进行进位。
而如果要进位我们需要将连续一段 \(1\) 变成 \(0\) ,再将一个 \(0\) 变成 \(1\)
考虑到这是区间推平和单点修改,我们可以使用线段树维护,但是由于对每个点都要维护,所以我们考虑使用主席树。
对于区间推平,我们先建出一个全部节点权值为 \(0\) 的主席树,然后将对应区间上的节点接到我们所需区间即可。
对于单点修改没什么好说的。
我们加法一共要执行 \(m\) 次,也就是说加法的总时间复杂度是 \(m\log n\)
比大小
直接比,肯定不行。
考虑哈希,找到第一个不同的位置,然后比较两数大小即可,直接线段树二分即可。
我们使用优先队列要耗费 \(q\log n\) 的时间复杂度,加上线段树二分,就是 \(q\log n\log |V|\) 的时间复杂度。
总时间复杂度 \(m\log n+q\log n\log |V|\)
空间复杂度 \(m\log |V|\)
点击查看代码
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int MAXN=1e5+100,N=1e5+20,MODD=1e9+7,NN=MAXN*77;
int n,m,S,T,tot;
int pw[N];
struct daduoli {
int f,t,w;
}que[MAXN*2];
int cnt,h[MAXN];
void add(int f,int t,int w) {
que[++cnt].f=h[f];
que[cnt].t=t;
que[cnt].w=w;
h[f]=cnt;
}
int rt[MAXN],sf[MAXN],pre[MAXN];
struct trr {
int lc[NN],rc[NN],sum[NN],sz[NN];
LL hs[NN];
void zt(int x,int v) {
lc[x]=lc[v]; sum[x]=sum[v];
rc[x]=rc[v]; sz[x]=sz[v]; hs[x]=hs[v];
}
void psup(int x) {
sum[x]=sum[lc[x]]+sum[rc[x]];
hs[x]=((LL)pw[sz[lc[x]]]*hs[rc[x]]%MODD+hs[lc[x]])%MODD;
}
void build(int &x,int l,int r) {
x=++tot;
sz[x]=r-l+1; hs[x]=0;
if(l==r) return ;
int mid=(l+r)/2;
build(lc[x],l,mid);
build(rc[x],mid+1,r);
psup(x);
}
void insert(int &x,int u,int l,int r,int w) {
x=++tot; zt(x,u);
if(l==r) {
++hs[x];
++sum[x];
return ;
}
int mid=(l+r)/2;
if(w<=mid) insert(lc[x],lc[u],l,mid,w);
if(w>mid) insert(rc[x],rc[u],mid+1,r,w);
psup(x);
}
void update(int &x,int u,int ori,int l,int r,int L,int R) {
if(l>=L&&r<=R) {
x=ori;
return ;
}
x=++tot; zt(x,u);
int mid=(l+r)/2;
if(L<=mid) update(lc[x],lc[u],lc[ori],l,mid,L,R);
if(R>mid) update(rc[x],rc[u],rc[ori],mid+1,r,L,R);
psup(x);
}
int query(int x,int l,int r,int L,int R) {
if(l>R||r<L) return 0;
if(l>=L&&r<=R) return sum[x];
int mid=(l+r)/2;
return (query(lc[x],l,mid,L,R)+query(rc[x],mid+1,r,L,R));
}
int QUERY(int x,int l,int r,int p,int num) {
if(l==r) return l;
int mid=(l+r)/2;
if(sum[lc[x]]>=mid-p+1+num) return QUERY(rc[x],mid+1,r,p,num-sum[lc[x]]);
return QUERY(lc[x],l,mid,p,num);
}
void mdf(int &x,int lst,int w) {
int c=(w>0?query(lst,0,N,0,w-1):0);
int y=QUERY(lst,0,N,w,c);
if(y>w) update(x,lst,rt[0],0,N,w,y-1);
else x=lst;
insert(x,x,0,N,y);
}
bool cmp(int a,int b,int l,int r) {
if(l==r) return sum[a]>sum[b];
int mid=(l+r)/2;
if(hs[rc[a]]==hs[rc[b]]) return cmp(lc[a],lc[b],l,mid);
return cmp(rc[a],rc[b],mid+1,r);
}
} T1;
void init() {
pw[0]=1;
for(int i=1;i<=N-1;++i) pw[i]=pw[i-1]*2%MODD;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
}
struct ddl {
int id,rt;
bool operator <(const ddl &a)const {
return T1.cmp(rt,a.rt,0,N);
}
};
priority_queue<ddl> q;
void dij() {
T1.build(rt[0],0,N); rt[S]=rt[0]; q.push({S,rt[S]});
while(!q.empty()) {
int u=q.top().id; q.pop();
if(sf[u]) continue; sf[u]=1;
if(u==T) break;
for(int i=h[u];i;i=que[i].f) {
int t=que[i].t;
T1.mdf(rt[n+1],rt[u],que[i].w);
if(!rt[t]||T1.cmp(rt[t],rt[n+1],0,N)) {
rt[t]=rt[n+1];
pre[t]=u;
q.push({t,rt[t]});
}
}
}
if(!sf[T]) {
puts("-1");
exit(0);
}
else printf("%lld\n",T1.hs[rt[T]]);
int x=T,cnt=0;
vector<int> e;
while(x) {
++cnt;
e.push_back(x);
x=pre[x];
}
printf("%d\n",cnt);
for(int len=e.size()-1,i=len;i>=0;--i) {
printf("%d ",e[i]);
}
}
int main () {
init();
scanf("%d%d",&S,&T);
dij();
return 0;
}
/*
4 3
1 2 0
2 3 0
3 4 0
1 4
*/
原文地址:https://www.cnblogs.com/ddl1no2home/p/17658542.html
- 程序员必知的6点编程秘诀,编程三板斧将解决90%问题!
- JavaScript之面向对象学习三原型语法升级
- 腾讯入局物业管理,欲改造传统服务?
- JavaScript之面向对象学习五(JS原生引用类型Array、Object、String等等)的原型对象介绍
- SQL学习之分组数据Group by
- SQL学习之数据列去空格函数
- 采用DIV+CSS布局对SEO优化有何好处?
- Sublime快速入门
- SQL学习之汇总数据之聚集函数
- Sedo榜单中,域名“加密世界”CryptoWorld.com七位数夺冠
- ExtJs学习笔记(20)-利用ExtJs的Ajax与服务端WCF交互
- 2018年热点分享:比特币到底是什么?
- JVM快速入门
- SQL学习之使用常用函数处理数据
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP count_chars()函数讲解
- 浅谈keras使用中val_acc和acc值不同步的思考
- PHP安装BCMath扩展的方法
- keras实现多GPU或指定GPU的使用介绍
- 浅谈keras中的keras.utils.to_categorical用法
- python 使用多线程创建一个Buffer缓存器的实现思路
- keras.utils.to_categorical和one hot格式解析
- Python OpenCV读取中文路径图像的方法
- Java如何基于wsimport调用wcf接口
- Python装饰器结合递归原理解析
- Windows上php5.6操作mongodb数据库示例【配置、连接、获取实例】
- 浅谈keras通过model.fit_generator训练模型(节省内存)
- PHP实现通过文本文件统计页面访问量功能示例
- 解决Alexnet训练模型在每个epoch中准确率和loss都会一升一降问题
- python里的单引号和双引号的有什么作用