题面:

A:公园

DAG上想拓扑dp

然而博主记忆化搜索了一下

设f[i][j]表示从i节点走j个点出公园所用的最小时间

则$f[u][i]=min(f[v][j-1]+dis_{u,v})$;

然后记忆化搜索

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define int long long
#define re register
#define MAXV 2005
#define MAXE 6005
using namespace std;
int v,m,n,e,l,a[MAXE],b[MAXE],ans=0;
int to[MAXE],nxt[MAXE],pre[MAXV],cnt=0,val[MAXE];
inline void add(re int u,re int v,re int w){
++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt,val[cnt]=w;
}
int ent[MAXE],f[MAXV][MAXV];
bool vis[MAXV];
inline void dfs(re int x){
if(x==v+1){
f[x][0]=0;
return ;
}
for(re int i=pre[x];i;i=nxt[i]){
re int y=to[i];
if(!vis[y]){
vis[y]=1;
dfs(y);
}
for(re int j=1;j<=v;j++)
f[x][j]=min(f[x][j],f[y][j-1]+val[i]);
}
}
signed main(){
//freopen("ex_park3.in","r",stdin);
scanf("%lld%lld%lld%lld%lld",&v,&m,&n,&e,&l);
for(re int i=0;i<=v+1;++i) for(re int j=0;j<=v+1;++j) f[i][j]=0x3fffffffffffffff;
for(re int i=1,x;i<=m;++i){
scanf("%lld",&x);
scanf("%lld",&a[x]);
ent[i]=x;
}
for(re int i=1,x;i<=n;++i){
scanf("%lld",&x);
scanf("%lld",&b[x]);
add(x,v+1,b[x]);
}
for(re int i=1,p,q,w;i<=e;++i){
scanf("%lld%lld%lld",&p,&q,&w);
add(p,q,w);
}
for(re int i=1;i<=m;++i){
if(vis[ent[i]]) continue;
vis[ent[i]]=1;
dfs(ent[i]);
}
for(re int i=1;i<=m;++i){
for(re int j=1;j<=v;++j){
if(f[ent[i]][j]+a[ent[i]]>l) continue;
ans=max(ans,j);
}
}
printf("%lld\n",ans);
return 0;
}

B:计划

先想一个暴力

我们预处理一个b[i],表示由i位置之后经过b[i]后是第一次出现m个不同的数

然后对于每一个询问(x,y),$ans=\sum\limits_{i=x}^{y}\frac{(y+b[i]-2i)*(y-b[i]+1)}{2}(b[i]<y)$

我们发现b[i]是单调增的,所以枚举到第一个b[i]>y就break

于是有80分

然后我们优化

我们发现$(y+b[i]-2i)*(y-b[i]+1)=y^2+y+b[i]-b[i]^2+2ib[i]-2i-2iy$

这个可以前缀和优化

那么重点就是找到第一个b[i]>y的位置,二分即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100005
#define re register
#define int long long
using namespace std;
int n,m,q,a[MAXN],b[MAXN],sum[MAXN],cnt[MAXN];
bool vis[MAXN];
inline int get(re int l){
re int num=0;
memset(vis,0,sizeof(vis));
for(re int i=l;i<=n;++i){
if(vis[a[i]]==0) num++;
vis[a[i]]=1;
if(num>=m) return i;
}
return n+1;
}
signed main(){
scanf("%lld%lld%lld",&n,&m,&q);
for(re int i=1;i<=n;++i){
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;++i){
b[i]=get(i);
if(b[i]>n) continue;
sum[i]=sum[i-1]+b[i]-b[i]*b[i]+2*i*b[i]-2*i;
cnt[i]=cnt[i-1]+i;
}
while(q--){
re int x,y,res=0,l,r,mid;
scanf("%lld%lld",&x,&y);
l=x,r=y;
while(l<=r){
mid=(l+r)>>1;
if(b[mid]<=y) l=mid+1;
else r=mid-1;
}
res+=(sum[l-1]-sum[x-1]+(l-x)*(y*y+y)-2*y*(cnt[l-1]-cnt[x-1]))/2;
printf("%lld\n",res);
}
return 0;
}

最新文章

  1. C#递归遍历子目录与子目录中的文件
  2. PHP实现新浪长链接转化成短链接API
  3. linux实用命令语句
  4. Flexbox,更优雅的布局
  5. Theano2.1.15-基础知识之theano如何处理shapre信息
  6. [转] 基于 Apache Mahout 构建社会化推荐引擎
  7. kinect for windows sdk
  8. centos使用denyhosts的问题,会将自己的IP自动加到hosts.deny的解决办法。
  9. jQuery.serializeArray() 函数详解
  10. java jvm学习笔记七(jar包的代码认证和签名)
  11. Js正则表达式提取图片地址
  12. PHP基于变量的引用实现的树状结构
  13. [SignalR]注册路由
  14. [BZOJ4518]征途
  15. GC机制总结
  16. 清除cookie
  17. (分治法 快速幂)P1226 【模板】快速幂||取余运算 洛谷
  18. day2 查看文件目录命令:ls
  19. 使用VS2013自带的PreEmptive Dotfuscator and Analytis来混淆C#代码
  20. [原][osg]osg文件与osgb文件的区别

热门文章

  1. 尚学python课程---14、python中级语法
  2. System.Web.Mvc.RouteAttribute.cs
  3. SpringCloud学习笔记(六):Feign+Ribbon负载均衡
  4. 实验室系统tomcat 6 java.lang.OutOfMemoryError: Java heap space
  5. Identifying a Blocking Query After the Issuing Session Becomes Idle
  6. django汉化
  7. pom.xml文件配置maven仓库地址
  8. 【默默努力】vue-pc-app
  9. COMMENT方法 用于在生成的SQL语句中添加注释内容,
  10. SQLite C++ Wrapper 是一个 C++ 语言对 SQLite 的最小封装包。