题目

W神爷的题解

高级数据结构

T1:

其实是一道easy题,$O(n^3log n)$ 也是能卡过去的,本着要的70分的心态,最后尽然A了。

如果是正解则是$O(n^3)$,当确定你要选择的列时,不断往下扩展,因为此刻是单调函数,所以可以用单调队列优化。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int n,a[][],s[][],hs[][],k,maxn;
bool check(int x1,int y1,int x2,int y2){return hs[x2][y2]-hs[x2][y1-]-hs[x1-][y2]+hs[x1-][y1-]<=k;}
int main()
{
n=read(),k=read();
for(int i=;i<=n;i++){
for(int j=;j<=n;j++) a[i][j]=read(),s[i][j]=s[i][j-]+a[i][j];
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++) hs[i][j]=hs[i-][j]+s[i][j];
}
for(int y1=;y1<=n;y1++){
for(int y2=y1;y2<=n;y2++){
int l=;
for(int r=;r<=n;r++){
while(!check(l,y1,r,y2)) l++;
maxn=max(maxn,(r-l+)*(y2-y1+));
}
}
}
printf("%d\n",maxn);
return ;
}

O(n^3)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int n,a[][],s[][],hs[][],k,maxn;
bool check(int x1,int y1,int x2,int y2){
int s1=,s2=,s3=;
s1=s[x1][y2]-s[x1][y1-];
if(x1!=x2)s2=s[x2][y2]-s[x2][y1-];
if(x2>x1+) s3=(hs[x2-][y2]-hs[x1][y2])-(hs[x2-][y1-]-hs[x1][y1-]);
if(s1+s2+s3>k) return ;
return ;
}
int towfen(int x1,int y1,int x2,int ll,int rr){
int l=ll,r=rr,mid,maxn=;
while(l<=r){
mid=l+r>>;
if(check(x1,y1,x2,mid)) maxn=max(maxn,mid),l=mid+;
else r=mid-;
}return maxn;
}
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
n=read(),k=read();
if(n*n<=k){
cout<<n*n;
return ;
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++) a[i][j]=read(),s[i][j]=s[i][j-]+a[i][j];
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++) hs[i][j]=hs[i-][j]+s[i][j];
}
for(int x1=;x1<=n;x1++)
{
for(int y1=;y1<=n;y1++)
{
for(int x2=n;x2>=x1;x2--)
{
if((n-y1+)*(x2-x1+)<=maxn) break;
int y2=towfen(x1,y1,x2,y1,n);
maxn=max(maxn,(x2-x1+)*(y2-y1+));
}
}
}
printf("%d",maxn);
return ;
}
/*
5 4
1 0 1 0 1
0 1 0 0 0
1 0 1 0 0
1 1 1 1 1
0 0 1 0 1
*/

O(n^3logn)

T2:

考试时的想法:看到题,发现与YBT的一本通上的一道题十分类似(this),所以就一直在想最小生成树,就再打,打了半天,发现这个方法正确性不显然,打完了,与自己的暴力程序对拍,WAWAWA,全是WA,心态炸了,最后交了个暴力程序,其实树形dp也是想过,但没有想过这么强大的后效性怎么处理掉,所以就放弃了。

$30points$:暴力

$extra 40 points$:

dp方程,设$dp(i)$表示前$i$ 个城市的代价均已计算,且最后一个机场设在了第$i$个城市的最小花费,所以就可以瞎搞了?为什么这样无后效性呢,是因为$dp$方程设计时是算出前面的,为什么与后面的无影响呢,因为可以传参

$100 points$:

树形$dp$.一个现在很明显的东西,所以要设计一个无后效性,快速的方程,然后其实就跟上面的一样了,详情看W神爷的题解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
int u,v,w,nex;
}x[];
int g[],cnt,dis[][],n,cost[],head[],dp[][];
void add(int u,int v,int w){
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],x[cnt].w=w,head[u]=cnt++;
}
void dfs(int f,int fa,int w,int root){
dis[root][f]=w;
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fa) continue;
dfs(x[i].v,f,w+x[i].w,root);
}
}
void dp_tree(int f,int fa){
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fa) continue;
dp_tree(x[i].v,f);
}
for(int i=;i<=n;i++){
dp[f][i]=cost[i]+dis[f][i];
for(int j=head[f];j!=-;j=x[j].nex){
if(x[j].v==fa) continue;
dp[f][i]+=min(g[x[j].v],dp[x[j].v][i]-cost[i]);
}
}
for(int i=;i<=n;i++) g[f]=min(g[f],dp[f][i]);
return;
}
int main()
{
// freopen("design.in","r",stdin);
// freopen("design.out","w",stdout);
memset(head,-,sizeof(head));
memset(g,/,sizeof(g));
n=read();
for(int i=;i<=n;i++) cost[i]=read();
for(int i=;i<n;i++){int u=read(),v=read(),w=read();add(u,v,w),add(v,u,w);}
for(int i=;i<=n;i++) dfs(i,,,i);
dp_tree(,);
cout<<g[];
}
/*
6
2 1 2 4 2 3
1 2 4
1 3 4
2 6 2
2 4 100
4 5 2
*/

T3:

线段树优化建图,以前不知道的东西,其实也是一个比较好想的方法,就是建一棵以$n$作为长度的线段树,用$dfs$的时间戳进行编号,方便建图。先将父亲节点向两个儿子连一条长度为$0$的边,然后再每个点向线段树中所对应的点连一条边权为$0$的边。因为每个点有一个移动距离所以可以二分求出它可以到达的左右端点,然后再跑$dijkstra$即可($spfa$,它死了)。为什么这样写是对的呢,为什么要建边权$0$边呢,是因为要保持可连通关系,就像能量流动一样,必须有层传导关系,给下面进行贡献,为什么不向上连边,是因为上面包含的区间比下面的长,就这么简单。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
long long u,v,w,nex;
}x[];
long long head[],dis[],vis[],pos[],w[],t[],n,ll[],rr[],cnt,s1,s2;
void add(long long u,long long v,long long w){
x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++;
}
long long query_l(long long dis,long long p){
long long l=,r=n,mid,minn=<<-,pp=dis-p;
while(l<=r){
mid=l+r>>;
if(pp<=pos[mid]) minn=min(minn,mid),r=mid-;
else l=mid+;
}
return minn;
}
long long query_r(long long dis,long long p){
long long l=,r=n,maxn=,mid,pp=dis+p;
while(l<=r){
mid=l+r>>;
if(pp>=pos[mid]) maxn=max(maxn,mid),l=mid+;
else r=mid-;
}
return maxn;
}
void build(long long k,long long l,long long r){
if(l==r){add(k+n,l,);return;}
long long mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
add(k+n,(k<<)+n,),add(k+n,(k<<|)+n,);
return;
}
void query(long long k,long long l,long long r,long long x,long long y,long long w,long long st){
if(x<=l&&r<=y){add(st,k+n,w);return;}
long long mid=l+r>>;
if(x<=mid) query(k<<,l,mid,x,y,w,st);
if(mid<y) query(k<<|,mid+,r,x,y,w,st);
return;
}
void dijkstra(){
memset(dis,,sizeof(dis));
priority_queue<pair<long long,long long> > que;
dis[s1]=;
que.push(make_pair(,s1));
while(!que.empty()){
long long xx=que.top().second;que.pop();
if(vis[xx]) continue;
vis[xx]=;
for(long long i=head[xx];i!=-;i=x[i].nex){
if(dis[x[i].v]>dis[xx]+x[i].w){
dis[x[i].v]=dis[xx]+x[i].w;
que.push(make_pair(-dis[x[i].v],x[i].v));
}
}
}
return;
}
int main()
{
memset(head,-,sizeof(head));
n=read(),s1=read(),s2=read();
for(long long i=;i<=n;i++) pos[i]=read();
for(long long i=;i<=n;i++) w[i]=read();
for(long long i=;i<=n;i++) t[i]=read();
for(long long i=;i<=n;i++) ll[i]=query_l(pos[i],w[i]),rr[i]=query_r(pos[i],w[i]);
build(,,n);
for(long long i=;i<=n;i++) query(,,n,ll[i],rr[i],t[i],i);
dijkstra();
cout<<dis[s2];
}

分数:$100+30+60=190$

20181022 考试记录&高级数据结构的更多相关文章

  1. GO语言的进阶之路-Golang高级数据结构定义

    GO语言的进阶之路-Golang高级数据结构定义 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们之前学习过Golang的基本数据类型,字符串和byte,以及rune也有所了解, ...

  2. Python中的高级数据结构

    数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数据结构,分别是List.Tuple.Dictionar ...

  3. Python中的高级数据结构详解

    这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考 ...

  4. Python中的高级数据结构(转)

    add by zhj: Python中的高级数据结构 数据结构 数据结构的概念很好理解,就是用来将数据组织在一起的结构.换句话说,数据结构是用来存储一系列关联数据的东西.在Python中有四种内建的数 ...

  5. 数据结构(5) 第五天 快速排序、归并排序、堆排序、高级数据结构介绍:平衡二叉树、红黑树、B/B+树

    01 上次课程回顾 希尔排序 又叫减少增量排序 increasement = increasement / 3 + 1 02 快速排序思想 思想: 分治法 + 挖坑填数 分治法: 大问题分解成各个小问 ...

  6. 高级数据结构之 BloomFilter

    高级数据结构之 BloomFilter 布隆过滤器 https://en.wikipedia.org/wiki/Bloom_filter A Bloom filter is a space-effic ...

  7. JS高级-数据结构的封装

    最近在看了<数据结构与算法JavaScript描述>这本书,对大学里学的数据结构做了一次复习(其实差不多忘干净了,哈哈).如果能将这些知识捡起来,融入到实际工作当中,估计编码水平将是一次质 ...

  8. 数据结构与算法——常用高级数据结构及其Java实现

    前文 数据结构与算法--常用数据结构及其Java实现 总结了基本的数据结构,类似的,本文准备总结一下一些常见的高级的数据结构及其常见算法和对应的Java实现以及应用场景,务求理论与实践一步到位. 跳跃 ...

  9. [总结] NOIP 前的考试记录

    sb博主又犯sb错误了! 他觉得以往模拟赛因为犯sb错误扔的分足足有1k分了! 于是他想记录一下自己犯的sb错误看看自己到底有多sb! 嗯就从今天开始吧 2018.9.28 1. 二分边界写错.骚什么 ...

随机推荐

  1. Qt 3D Studio 1.0 Resleased

    Qt 这家伙又整出一个新东西了,Qt 3D Studio 1.0 新闻链接:https://blog.qt.io/blog/2017/11/30/qt-3d-studio-1-0-released/ ...

  2. 使用httpClient获取请求cookie

    package mytest; import java.util.ArrayList; import java.util.List; import org.apache.http.NameValueP ...

  3. jmeter获取cookies

    使用场景:登录后,后续的请求操作需获取到JSESSIONID才可进行 1.将jmeter的bin目录下的jmeter.properties文件中的CookieManager.save.cookies= ...

  4. Siki_Unity_2-1_API常用方法和类详细讲解(上)

    Unity 2-1 API常用方法和类详细讲解(上) 任务1&2:课程前言.学习方法 && 开发环境.查API文档 API: Application Programming I ...

  5. [HNOI2017]大佬

    参考题解 \(\text{Solution}\) 我们发现5个行为中2操作与其它操作无关,所以我们采用贪心,尽量让多的时间去攻击大佬. 设 \(f[i][j]\) 表示前 \(i\) 天剩 \(j\) ...

  6. CryptoZombies学习笔记——Lesson3

    第三课就开始深入讲解solidity编程技巧了. chapter1: 智能合约的不变性. 合约一旦部署到以太坊后,就不可更改了,所以从一方面来说,智能合约代码的安全性是如此重要,因为一旦发现你的代码里 ...

  7. Linux内核设计笔记7——中断

    中断与中断处理 何为中断? 一种由设备发向处理器的电信号 中断不与处理器时钟同步,随时可以发生,内核随时可能因为中断到来而被打断. 每一个中断都有唯一一个数字标志,称之为中断线(IRQ) 异常是由软件 ...

  8. 《javascript模式--by Stoyan Stefanov》书摘--汇总

    <javascript模式--by Stoyan Stefanov>书摘--基本技巧 http://www.cnblogs.com/liubei/p/JavascriptModeLog1. ...

  9. Unicode,UTF-32,UTF-16,UTF-8到底是啥关系?

    编码的目的,就是给抽象的字符赋予一个数值,好在计算机里面表示.常见的ASCII使用8bit给字符编码,但是实际只使用了7bit,最高位没有使用,因此,只能表示128个字符:ISO-8859-1(也叫L ...

  10. Python练习—文件

    1.随机生成20个两位正整数,将其升序排序后再写入文本文件data_asc.txt中! import random alist = [random.randint(10,100) for i in r ...