A 货物收集

显然是一个二分答案的题。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e6+,INF=0x3f3f3f3f;
int val[N];
int n,L,R,w;
struct thxorz{
int head[N],nxt[N<<],to[N<<],w[N<<],tot;
inline void add(int x,int y,int z){
to[++tot]=y,nxt[tot]=head[x],head[x]=tot,w[tot]=z;
to[++tot]=x,nxt[tot]=head[y],head[y]=tot,w[tot]=z;
}
}G;
#define y G.to[j]
inline int dfs(int mid,int x,int fa){
int ret=val[x];
for(register int j=G.head[x];j;j=G.nxt[j])if(y^fa&&G.w[j]<=mid)ret+=dfs(mid,y,x);
return ret;
}
#undef y
int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout);
read(n),read(w);L=INF;
for(register int i=;i<=n;++i)read(val[i]);
for(register int i=,x,y,z;i<n;++i)read(x),read(y),read(z),G.add(x,y,z),MIN(L,z),MAX(R,z);
int mid;
while(L<R){
mid=L+R>>;
if(dfs(mid,,)>=w)R=mid;
else L=mid+;
}
printf("%d\n",L);
return ;
}

B 货物分组

写出一个裸的DP方程。$O(n^3)$.

$f_{i,k}=\min\{f_{j,k-1}+k(sum_i-sum_{j-1})+\max_{j+1\sim i}-\min_{j+1\sim i}\}$

然后因为这个涉及和$k$相关的乘积项,为了简化$k$这一维的状态,采用费用预算的思想,将后面所有组都提前加上一次他们总和。

所以去掉$k$这一维,$O(n^2)$。

$f_i=\min\{f_j-sum_j+\max_{j+1\sim i}-\min_{j+1\sim i}\}$

然后要考虑优化。我DP优化学傻掉了。`````

发现max和min实际上每次都是一个元素控制他前面的一段区间。这个可以用单调栈求出,然后max若干段区间和min若干段区间,每段最值都相同。那么,把方程前两项压入线段树,然后后面的max和min通过修改来完成:每次更新区间的时候,把弹栈的若干区间里的状态去掉他们原来的最值,加上新加入栈的最值。这个就是个区间修改,然后线段树维护最小值,每次转移区间查询即可。$O(n\log n)$。

这里用了标记永久化,实际上是学hkk的,可以发现常数小一些,核心在于在某节点内部的区间上传信息时都要加上自己打的标记。

WA*1:线段树里下标表示对应的状态前两项,单调栈里是最值。。搞反了导致line54~line57出错。。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+;
const ll INF=1ll<<;
struct segment_tree{
ll minv[N<<],atag[N<<];
#define lc i<<1
#define rc i<<1|1
// segment_tree(){memset(minv,0x3f,sizeof minv);}
void update_add(int i,int L,int R,int ql,int qr,ll val){
if(ql<=L&&qr>=R)return minv[i]+=val,atag[i]+=val,void();
int mid=L+R>>;
if(ql<=mid)update_add(lc,L,mid,ql,qr,val);
if(qr>mid)update_add(rc,mid+,R,ql,qr,val);
minv[i]=_min(minv[lc],minv[rc])+atag[i];
}
ll query_min(int i,int L,int R,int ql,int qr){
if(ql<=L&&qr>=R)return minv[i];
int mid=L+R>>;ll ret=INF;
if(ql<=mid)MIN(ret,query_min(lc,L,mid,ql,qr));
if(qr>mid)MIN(ret,query_min(rc,mid+,R,ql,qr));
return ret+atag[i];
}//pay attention to the permanent tag...
}T;
int stkmin[N],stkmax[N],A[N],top1,top2;
ll s[N],f[N];
int n,w,lb; int main(){//freopen("2.in","r",stdin);//freopen("test.ans","w",stdout);
read(n),read(w);stkmin[]=stkmax[]=-;
for(register int i=;i<=n;++i)s[i]=s[i-]+read(A[i]);
for(register int i=;i<=n;++i){//dbg(i);
T.update_add(,,n-,i-,i-,f[i-]+s[n]-s[i-]);
while(top1&&A[stkmin[top1]]>=A[i])T.update_add(,,n-,stkmin[top1-],stkmin[top1]-,A[stkmin[top1]]),--top1;
T.update_add(,,n-,stkmin[top1],i-,-A[i]),stkmin[++top1]=i;//dbg(top1);
while(top2&&A[stkmax[top2]]<=A[i])T.update_add(,,n-,stkmax[top2-],stkmax[top2]-,-A[stkmax[top2]]),--top2;
T.update_add(,,n-,stkmax[top2],i-,A[i]),stkmax[++top2]=i;//dbg(top2);
while(s[i]-s[lb]>w)++lb;
f[i]=T.query_min(,,n-,lb,i-);
}
printf("%lld\n",f[n]);
return ;
}

C 地形计算

复杂度计算非常神仙的一个题。其实这题复杂度我也不会算,以下为口胡

顺便学习了一下三元环和四元环的计数。连接1(有复杂度证明)连接2(好像做法不对?)连接3

三元环的话主要就是因为定了向,好处有二:一是每个环只会被计一次,二是复杂度可以利用这个度数大小关系证出来是根号的。

四元环的话,类似。原来的三元环是度数大的向度数小的走,现在为了走四元环保证复杂度,只能每次走深度为2的路(相当于就走了一次三元环),然后所有终点相同、深度为二的里做统计计算。

不过并不是边直接从度数大的走向小的,这样会有四元环被漏计,为了保证每个环被算一次且仅一次,改变走边方法,枚举每一个起点$x$,然后枚举走到的$y$,要求度数$x>y$(相等时按编号),然后再从$y$开始遍历走到的$z$,要求度数也有$z<x$,这样,每个环只会被度数最大的那个点统计到。同时还可以保证复杂度:假设现在$y$度数小于$\sqrt{M}$,则$x$遍历图中每条边,到达的点向外拓展,复杂度$O(M\sqrt{M})$。若$y$度数大于$\sqrt{M}$,则利用度数传递性,$x$度数也应当大于根号,所以得知总的这样的$x$不会超过根号个,所以每一个$y$有不超过根号个入点$x$进来,对于每一个点$y$贡献复杂度$O(\sqrt{M}outdegree_y)$,又因为$\sum outdegree_y\le m$,所以总体也是$O(M\sqrt{M})$的。证毕。其实这也是三元环复杂度的证明方法。

然后这题就算权值就好了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+,P=1e9+;
struct thxorz{
int head[N],nxt[N<<],to[N<<],tot;
inline void add(int x,int y){
to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
}
}G;
int val[N],deg[N],vis[N],sum[N],cnt[N];
int n,m,ans;
inline void add(int&a,int b){((a+=b)>=P)&&(a-=P);}
inline int mod(int a){return a>=P?a-P:a;} int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n),read(m);
for(register int i=;i<=n;++i)read(val[i]);
for(register int i=,x,y;i<=m;++i)read(x),read(y),G.add(x,y),++deg[x],++deg[y];
#define y G.to[i]
#define z G.to[j]
for(register int x=;x<=n;++x){
for(register int i=G.head[x];i;i=G.nxt[i])if(deg[y]<deg[x]||deg[x]==deg[y]&&y<x){
for(register int j=G.head[y];j;j=G.nxt[j])if(deg[z]<deg[x]||deg[z]==deg[x]&&z<x){
if(vis[z]^x)vis[z]=x,cnt[z]=,sum[z]=val[y];
else add(ans,mod(cnt[z]*1ll*(val[x]+val[z]+0ll+val[y])%P+sum[z])),++cnt[z],add(sum[z],val[y]);
}
}
}
printf("%d\n",ans);
return ;
}

牛客CSP-S提高组赛前集训营3的更多相关文章

  1. 牛客网CSP-S提高组赛前集训营Round4

    牛客网CSP-S提高组赛前集训营 标签(空格分隔): 题解 算法 模拟赛 题目 描述 做法 \(BSOJ6377\) 求由\(n\)长度的数组复制\(k\)次的数组里每个连续子序列出现数字种类的和 对 ...

  2. 牛客CSP-S提高组赛前集训营1

    牛客CSP-S提高组赛前集训营1 比赛链接 官方题解 before:T1观察+结论题,T2树形Dp,可以换根或up&down,T3正解妙,转化为图上问题.题目质量不错,但数据太水了~. A-仓 ...

  3. 牛客CSP-S提高组赛前集训营3 赛后总结

    货物收集 二分答案.复杂度\(O(n\log n)\). 货物分组 用费用提前计算的思想,考虑用一个新的箱子来装货物会发生什么. 显然费用会加上后面的所有货物的总重. \(60\)分的\(O(n^2) ...

  4. 牛客CSP-S提高组赛前集训营2 ———— 2019.10.31

    比赛链接 期望得分:100+20+20 实际得分:40+20+30 awa  cccc T1 :基于贪心的思路,然后开始爆搜(雾 那必然是会死的,好吧他就是死了 #include<iostrea ...

  5. 牛客CSP-S提高组赛前集训营1———2019.10.29 18:30 至 22:00

    期望得分:100+0+10 实际得分:40+0+0 考炸了... T1:题目链接 究竟为什么会这样,,, 仔细研读我的丑代码 发现... 枯辽.... #include<cstdio> # ...

  6. 牛客CSP-S提高组赛前集训营2 T2沙漠点列

    原题链接 算法不难,比赛的时候就和cyc大佬一起yy了正解,不过因为交的时候比较急(要回寝室惹),我有两数组开错大小直接爆到50,cyc大佬则只把文件输入关了一半,直接爆零(╯ ̄Д ̄)╯┻━┻ 要尽量 ...

  7. 20191029 牛客CSP-S提高组赛前集训营1

    前一个小时看这几道题感觉要爆零 A. 仓鼠的石子游戏 分析一下发现a[i]>1a[i]>1a[i]>1时后先手必输,a[i]=1a[i]=1a[i]=1时先手必赢 然后直接看1的个数 ...

  8. 牛客CSP-S提高组赛前集训营4 赛后总结

    复读数组 分成 3 种区间算答案: 一个块内的区间 两个块交界处,长度小于块长的区间 长度不小于块长的区间 对于第三种区间,容易发现每个区间的权值一样,只需要算出个数即可. 对于前两种空间,我的思路是 ...

  9. 牛客CSP-S提高组赛前集训营5 赛后总结

    A.无形的博弈 心理题. 答案为\(2^n\),可感性理解结论的正确性. #include<bits/stdc++.h> #define LL long long const LL Mod ...

随机推荐

  1. #论文阅读# Universial language model fine-tuing for text classification

    论文链接:https://aclweb.org/anthology/P18-1031 对文章内容的总结 文章研究了一些在general corous上pretrain LM,然后把得到的model t ...

  2. indows Eclipse Scala编写WordCount程序

    Windows Eclipse Scala编写WordCount程序: 1)无需启动hadoop,因为我们用的是本地文件.先像原来一样,做一个普通的scala项目和Scala Object. 但这里一 ...

  3. NEO4J (二)

    README 整理 kernel.impl.coreapi 这个包包含核心API的直接实现.核心API是org.neo4j中定义的API.graphdb及其子包. 这里的类是实现细节,可能会在不通知的 ...

  4. javaweb中关于转发与重定向的写法

    转发: RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/main.jsp"); rd.forward(r ...

  5. LC 394. Decode String

    问题描述 Given an encoded string, return its decoded string. The encoding rule is: k[encoded_string], wh ...

  6. NOIP 2018 提高组初赛试题 题目+答案+简要解析

    一.单项选择题(共 10  题,每题 2  分,共计 20  分: 每题有且仅有一个正确选项)       1. 下列四个不同进制的数中,与其它三项数值上不相等的是( ). A. (269) 16 B ...

  7. python+socket实现网络信息交互及文件传输

    Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket又称"套接字",应用程序通常通过"套接字" ...

  8. c c++各种类型的取值范围

    int类型的变量存储值从-2147483648到2147483647 //例子 #include <iostream> using namespace std; int main(void ...

  9. 第二章、http协议及嗅探抓包--http协议详解

    初识http协议    hypertext trandfer protocol 超文本传输协议,是一种分布式,合作式,多媒体信息系统服务,面向应用层的协议.使用最广泛的应用层协议,基于传输层的TCP协 ...

  10. vue-slick 插件配置

    autoplay 布尔值 false 自动播放 autoplaySpeed 整数 3000 自动播放间隔 centerMode 布尔值 false 中心模式 centerPadding 字符串 ’50 ...