牛客CSP-S提高组赛前集训营5 解题报告
时间:2019-11-08
本文章向大家介绍牛客CSP-S提高组赛前集训营5 解题报告,主要包括牛客CSP-S提高组赛前集训营5 解题报告使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
总分 : 100 + 100 + 40 = 240
T1
结论题。无论如何神J都会赢。
最优决策:神树变化了我就不变,神树不变我就变化。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
inline ll POW(ll pre, int x){
ll res=1;
for(; x; x>>=1,pre=pre*pre%mod)
if(x&1) res=res*pre%mod;
return res;
}
int n;
int main(){
scanf("%d",&n);
printf("%lld\n",POW(2,n));
return 0;
}
T2
状压DP水题。
暴力都没有去切,因为k太小了,直接状压走过那些边即可。
//代码有点丑,但是考试的时候挺快就敲出来了。
#include<bits/stdc++.h>
#define re register
#define rep(i,a,b) for(re int i=a,i##end=b; i<=i##end; i++)
#define drep(i,a,b) for(re int i=a,i##end=b; i>=i##end; i--)
#define repp(i,a,b) for(re int i=a,i##end=b; i<i##end; i++)
#define drepp(i,a,b) for(re int i=a,i##end=b; i>i##end; i--)
#define Erep(i,x) for(re int i=head[x]; i; i=Edge[i].nxt)
#define lowbit(x) ((x)&-(x))
#define debug(x) cerr<<#x<<" = "<<x<<endl
#define ms(x,a) memset(x,a,sizeof x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define fi first
#define se second
#define coint const int
#define coll const ll
#define CM cerr<<(&S2-&S1)/1024./1024<<"MB"<<endl
typedef long long ll;
using namespace std;
template<class T>inline T rd(){
static char ch;static bool neg;static T x;
for(ch=0, neg=0; ch>'9'||ch<'0'; neg|=(ch=='-'),ch=getchar());
for(x=0; ch>='0'&&ch<='9'; x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar());
return neg?-x:x;
}
template<class T>inline T Max(const T &x, const T &y) { return x>y?x:y; }
template<class T>inline T Min(const T &x, const T &y) { return x<y?x:y; }
bool S1;
coint N=50000+5,M=200000+5,K=12+5;
struct edge{
int to,val,nxt;
}Edge[M<<1];
int head[N],tcnt;
inline void AddEdge(coint u, coint v, coint w){
Edge[++tcnt]=(edge)<%v,w,head[u]%>;
head[u]=tcnt; return;
}
struct edge2{
int to,val,id;
};
vector<edge2>G[N];
vector<int>vec;
int n,m,k;
int mark[N],ID[N];
ll dis[K<<1][N];
ll dp[(1<<K)|5][K<<1];
struct node{
int x;
ll val;
bool operator < (const node &_) const { return val>_.val; }
};
struct Heap{
node sum[N+M];
int sz;
inline void pop(){
sum[1]=sum[sz--];
int now=1,nxt;
while(nxt=now<<1,nxt<=sz){
if(nxt<sz && sum[nxt]<sum[nxt|1]) nxt|=1;
if(sum[now]<sum[nxt]) swap(sum[nxt],sum[now]),now=nxt;
else break;
}
return;
}
inline void push(node x){
sum[++sz]=x;
int now=sz,nxt;
while(nxt=now>>1,nxt){
if(sum[nxt]<sum[now]) swap(sum[now],sum[nxt]),now=nxt;
else break;
}
return;
}
inline bool empty() { return !sz; }
inline void clear() { sz=0; return; }
inline int size() { return sz; }
inline node top() { return sum[1]; }
}Q;
//priority_queue<node>Q;
inline void Dijkstra(coint id, coint st){
Q.clear();
Q.push((node)<%st,0%>);
dis[id][st]=0;
while(!Q.empty()){
node now=Q.top(); Q.pop();
if(mark[now.x]==id) continue;
mark[now.x]=id;
Erep(i,now.x){
edge y=Edge[i];
coll res=y.val+now.val;
if(res<dis[id][y.to]){
dis[id][y.to]=res;
Q.push((node)<%y.to,res%>);
}
}
}
// rep(i,1,n) printf("%d -> %d : %lld\n",st,i,dis[id][i]);
return;
}
bool S2;
int main(){
// CM;
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
n=rd<int>(),m=rd<int>(),k=rd<int>();
rep(i,1,m){
coint u=rd<int>(),v=rd<int>(),w=rd<int>();
AddEdge(u,v,w); AddEdge(v,u,w);
if(i<=k){
G[u].push_back((edge2)<%v,w,i%>);
if(u!=v) G[v].push_back((edge2)<%u,w,i%>);
mark[u]=mark[v]=1;
}
}
mark[1]=1;
rep(i,1,n) if(mark[i]) vec.push_back((int)i),ID[i]=((int)vec.size())-1;
ms(mark,-1); ms(dis,0x3f);
repp(i,0,vec.size()) Dijkstra(i,vec[i]);
ms(dp,0x3f);
coll INF=dp[0][0];
dp[0][0]=0;
repp(sta,0,(1<<k)-1){
repp(i,0,vec.size()){
repp(j,0,vec.size()){
dp[sta][j]=Min(dp[sta][j],dp[sta][i]+dis[i][vec[j]]);
}
}
repp(i,0,vec.size()){
if(dp[sta][i]>=INF) continue;
int at=vec[i];
repp(j,0,(int)G[at].size()){
coint to=G[at][j].to,val=G[at][j].val,id=G[at][j].id;
if(sta&(1<<id>>1)) continue;
dp[sta|(1<<id>>1)][ID[to]]=Min(dp[sta|(1<<id>>1)][ID[to]],dp[sta][i]+val);
}
}
}
ll ans=INF;
repp(i,0,vec.size())
ans=Min(ans,dp[(1<<k)-1][i]+dis[i][1]);
printf("%lld\n",ans);
return 0;
}
T3
(pre_dfs与dfs_top是树链剖分的部分。)
P30
直接暴力\(O(n^3)\)处理处每两个点间最小Dis值
struct P30{
static coint N=300+5;
ll Dis[N][N];
inline void solve(){
pre_dfs(1,0); dfs_top(1,0,1);
rep(i,1,n){
int x=i;
while(x) Dis[x][i]=x*(dis[i]-dis[x]),x=f[x];
}
rep(i,1,n){
int x=i;
while(x){
int y=x;
while(y){
Dis[y][i]=Min(Dis[y][i],Dis[y][x]+Dis[x][i]);
y=f[y];
}
x=f[x];
}
}
rep(i,1,m){
int s=rd<int>(),t=rd<int>();
if(LCA(s,t)!=s) { puts("-1"); continue; }
printf("%lld\n",Dis[s][t]);
}
return;
}
}p30;
P40
可以发现询问数量很小,我们直接对于每个询问暴力向上跳,而我们总共就会处理\(n^2\)个点之间的距离,中间重复处理的还可以省去,因此总复杂度不到\(O(n^2)\)
struct P40{
static coint N=3000+5;
ll Dis[N][N];
bool mark[N][N];
inline void solve(){
pre_dfs(1,0); dfs_top(1,0,1);
rep(i,1,n){
Dis[i][i]=0;
int x=f[i];
while(x) Dis[x][i]=x*(dis[i]-dis[x]),x=f[x];
}
rep(i,1,m){
int s=rd<int>(),t=rd<int>();
if(LCA(s,t)!=s) { puts("-1"); continue; }
int x=t,fa=f[s];
if(!mark[s][t]) while(x!=fa){
if(mark[x][t]) { x=f[x]; continue; }
int y=t;
while(y!=x){
Dis[x][t]=Min(Dis[x][t],Dis[x][y]+Dis[y][t]);
y=f[y];
}
mark[x][t]=1;
x=f[x];
}
printf("%lld\n",Dis[s][t]);
}
return;
}
}p40;
P70
可以发现在向下跳的过程中,我们经过的点是单调递减的,因此利用倍增思想,记录下一个走到的点,以及其花费,然后倍增处理处即可。
struct P_Chain{
ll dis[N];
ll Dis[20][N];
int tp[20][N];
int dep[N],f[N];
void dfs(coint x, coint fa){
Erep(i,x){
edge y=Edge[i];
if(y.to==fa) continue;
dep[y.to]=dep[x]+1; f[y.to]=x; dis[y.to]=dis[x]+y.val;
dfs(y.to,x);
if(y.to<x) tp[0][x]=y.to;
else{
int z=tp[0][y.to];
while(z>=x && z) z=tp[0][z];
if(z) tp[0][x]=z;
}
if(tp[0][x]) Dis[0][x]=x*(dis[tp[0][x]]-dis[x]);
}
return;
}
inline void solve(){
dfs(1,0);
rep(j,1,19){
rep(i,1,n){
if(!tp[j-1][i] || !tp[j-1][tp[j-1][i]]) continue;
tp[j][i]=tp[j-1][tp[j-1][i]];
Dis[j][i]=Dis[j-1][i]+Dis[j-1][tp[j-1][i]];
}
}
rep(i,1,m){
int x=rd<int>(),y=rd<int>();
if(dep[x]>dep[y]) { puts("-1"); continue; }
ll ans=0;
drep(j,19,0){
if(dep[tp[j][x]]<dep[y] && tp[j][x]){
ans+=Dis[j][x];
x=tp[j][x];
}
}
ans+=1ll*(dis[y]-dis[x])*x;
printf("%lld\n",ans);
}
return;
}
}p_chain;
P100
还在写……施工ing
总结
链的30分没拿到真的不应该。思维还得更加活跃才可以。
原文地址:https://www.cnblogs.com/ppp204-is-a-VC/p/11818284.html
- 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 数组属性和方法
- python 制作python包,封装成可用模块教程
- 使用python脚本自动生成K8S-YAML的方法示例
- Python虚拟环境库virtualenvwrapper安装及使用
- tp5框架内使用tp3.2分页的方法分析
- YII框架常用技巧总结
- PHP连接SQL Server的方法分析【基于thinkPHP5.1框架】
- PHP切割汉字的常用方法实例总结
- Laravel Validator 实现两个或多个字段联合索引唯一
- php实现的顺序线性表示例
- pytorch快速搭建神经网络_Sequential操作
- PHP7使用ODBC连接SQL Server2008 R2数据库示例【基于thinkPHP5.1框架】
- Yii框架引入coreseek分页功能示例
- 使用keras内置的模型进行图片预测实例
- PHP convert_cyr_string()函数讲解
- 在keras中model.fit_generator()和model.fit()的区别说明