期望得分:70+100+60

实际得分:70+20+60 \(qwq\)。

T1:有一个 \(n\) × \(n\) 的 \(01\) 方格, 图图要从中选出一个面积最大的矩形区域, 要求这个矩形区域不能有超过 \(k\) 个 \(1\)。

开始只会\(O(n^4)\)算法,即枚举左上角和右下角,然后去写了T2&T3,回来想了一个多小时大概,还是没想出...但是造了大数据验证了一下暴力应该是没问题的。

70分暴力:

#include<cstdio>
#include<algorithm> using namespace std; int n,k,ans;
int mapp[600][600]; int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mapp[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mapp[i][j]+=mapp[i-1][j]+mapp[i][j-1]-mapp[i-1][j-1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int l=1;l<=n&&i-l+1>=1;l++)
for(int r=1;r<=n&&j-r+1>=1;r++)
{
int ii=i-l+1;
int jj=j-r+1;
int qwq=mapp[i][j]+mapp[ii-1][jj-1]-mapp[ii-1][j]-mapp[i][jj-1];
if(qwq>k) continue;
ans=max(ans,l*r);
}
printf("%d",ans);
return 0;
}

正解:很巧妙的想法:我们不需枚举那么多,有些是重复的。因为矩阵的二维前缀和是有单调性的。什么意思?我们枚举矩阵的上下界,然后只枚举一个右边界,左边界从1开始向右推进,显然在开始时刻包含的1最多,在不断向右推进的过程中包含的1越来越少,当找到一个满足\(k\)的时刻我们便停止向右推进,这时一定保证最优。因为右面的情况会越来越少。

#include<cstdio>
#include<algorithm> using namespace std; int n,k,ans;
int f[1000][1000]; int ask(int a,int b,int c,int d)
{
return f[c][d]+f[a-1][b-1]-f[a-1][d]-f[c][b-1];
} int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&f[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
int l=1;
for(int r=1;r<=n;r++)
{
while(ask(i,l,j,r)>k) l++;
ans=max(ans,(r-l+1)*(j-i+1));
}
}
printf("%d\n",ans);
return 0;
}

主要是这个单调性,它就是很显然的东西,但是如果不注意它的话就真找不到正解==。

T2:他正在玩一款策略游戏, 地图由 \(n\) 座城市组成, 并由 \(n - 1\) 条无向带权边连接成树形结构。 为了解决物资补给, 图图需要在这 \(n\) 座城市选出若干座城市建立机场, 其中在第 \(i\) 座城市建立机场的代价是 \(cost[i]\)。

建立机场之后, 每座城市得到补给的代价为该城市到最近机场的距离。 而他总共花费的代价即为建立机场的代价与每座城市得到补给的代价之和, 当然他想让这个代价最小。

考场上读完题后感觉是自己做过的原题然后就惨惨了。事后感觉一点也不一样啊,只是看起来很像⑧了(摔)。事实是考场上几乎不会出原题的,如果感觉像一定要一再尝试否认自己。不能盲目自信==。

这种最优化&在树上背景,大多是树形dp。我竟然从没向这想过(。首先我们考虑一条链的情况,\(f[i]\)表示前\(i\)个城市的代价均已计算,最后一个机场设在第\(i\)个城市的最小花费。转移:

https://cdn.luogu.org/upload/pic/41397.png

如果状态设计出来,这个转移应该还是不难理解的。考虑如何扩展到树的情况,一般我们设计树形dp的状态时,有诸如\(dp[i]\)为以\(i\)为根的子树\(balabala\)...的表述。

我们考虑设计这样一个状态:\(f[i][j]\)表示以\(i\)为根的子树,当前距离\(i\)最近的机场设在了\(j\),子树内所有城市花费之和的最小值,另设一个\(g[i]\)保存\(min{f[i][j]}\)。那么转移:有两部分我们是一定要花费的,\(i\)到\(j\)的距离和在\(j\)点建造的花费。其他:枚举\(i\)子树内的所有儿子\(v\),在\(g[v]\)和\(f[v][j]\)-\(val[j]\)中寻求最小。(减去\(val[j]\)是为了防止算多。)那么转移即为这样:

    for(int j=1;j<=n;j++)
{
f[u][j]=val[j]+dis[u][j];
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v!=fa) f[u][j]+=min(g[v],f[v][j]-val[j]);
}
}

可以看出我们还需要计算一下两点间的距离:因为是在一棵树上,因为复杂度被控制在不\(n^2\)内,那么我们可以从每个点出发进行一遍\(dfs\)求出这个距离。(感觉\(std\)的这个想法好巧妙啊x)

for(int i=1;i<=n;i++) dfs(i,0,i);

void dfs(int u,int fa,int s)
{
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa) continue;
dis[s][v]=dis[s][u]+edge[i].val;
dfs(v,u,s);
}
}

完整代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 2600 using namespace std; int n,tot;
int head[maxn],val[maxn],g[maxn],dis[maxn][maxn],f[maxn][maxn];
struct node{
int to,next,val;
}edge[maxn<<1]; void add(int x,int y,int z)
{
edge[++tot].to=y;
edge[tot].next=head[x];
head[x]=tot;
edge[tot].val=z;
} void dfs(int u,int fa,int s)
{
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa) continue;
dis[s][v]=dis[s][u]+edge[i].val;
dfs(v,u,s);
}
} void TreeDP(int u,int fa)
{
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v!=fa) TreeDP(v,u);
}
for(int j=1;j<=n;j++)
{
f[u][j]=val[j]+dis[u][j];
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v!=fa) f[u][j]+=min(g[v],f[v][j]-val[j]);
}
}
g[u]=f[u][1];
for(int i=1;i<=n;i++) g[u]=min(g[u],f[u][i]);
} int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<=n-1;i++)
{
int x=0,y=0,z=0;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z),add(y,x,z);
}
for(int i=1;i<=n;i++) dfs(i,0,i);
TreeDP(1,0);
printf("%d\n",g[1]);
return 0;
}

T3:他计划去 \(Bzeroth\) 的精灵王国去旅游, 精灵王国由 \(n\) 座城市组成, 第 \(i\) 座城市有 \(3\) 个属性 \(x[i]\), \(w[i]\), \(t[i]\)。

在精灵王国的城市之间穿行只能依靠传送阵, 第 \(i\) 座城市的传送阵可以将他从城市 \(i\) 传送到距离城市 \(i\) 不超过 \(w[i]\)的任意一个城市, 并需要 \(t[i]\)的时间完成传送。 现在他知道了每个城市的坐标 \(x[i]\), 想知道他从城市 \(s\) 到城市 \(t\) 的最小时间。

唔...读完题后感觉只会打\(60\)分的暴力,建边最坏复杂度\(O(n^2)\),跑\(dijistra\)复杂度\(O(mlogn)\),总复杂度近似为\(O(n^2logn)\)。

\(60\)分暴力:

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#define maxn 153000 using namespace std;
typedef long long ll; int n,s,t,tot;
int pos[maxn],dist[maxn],w[maxn],head[maxn];
ll dis[maxn];
bool vis[maxn];
struct node{
int to,next,val;
}edge[6300000]; void add(int x,int y,int z)
{
edge[++tot].to=y;
edge[tot].next=head[x];
head[x]=tot;
edge[tot].val=z;
} void dijkstra()
{
priority_queue<pair<ll,int> >q;
q.push(make_pair(0,s));
for(int i=1;i<=n;i++) dis[i]=2e9;
dis[s]=0;
while(!q.empty())
{
int u=q.top().second;q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(dis[v]>dis[u]+edge[i].val)
{
dis[v]=dis[u]+edge[i].val;
q.push(make_pair(-dis[v],v));
}
}
}
} int main()
{//60 pts
freopen("trip.in","r",stdin);
freopen("trip.out","w",stdout);
scanf("%d%d%d",&n,&s,&t);
for(int i=1;i<=n;i++) scanf("%d",&pos[i]);
for(int i=1;i<=n;i++) scanf("%d",&dist[i]);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<=n;i++)
{
int j=i+1;
while(pos[j]-pos[i]<=dist[i]&&j<=n)
{
add(i,j,w[i]);
j++;
}
j=i-1;
while(pos[i]-pos[j]<=dist[i]&&j>=1)
{
add(i,j,w[i]);
j--;
}
}
dijkstra();
printf("%lld\n",dis[t]);
return 0;
}

正解:这个复杂度的瓶颈其实就在建边上,首先很显然能建的边是一段连续的区间,我们可以优化用二分求得。然后我们可以从各点向这些连续区间连边!这就很像线段树的查询区间了,把这些区间在线段树上维护,那么从每个城市出发,会向\(O(logn)\)个区间连边,边数被降到了\(O(nlogn)\)。再跑\(dij\)就能稳过了。代码...写不出来,因为不会动态开点线段树(,先鸽了。

11-1模拟赛 By cellur925的更多相关文章

  1. 9.11 myl模拟赛

    9.11 myl 模拟赛 100 + 100 + 0 第一题耗费了太多的时间,导致最后一题没有时间想,直接去写了暴力,而且出题人没有给暴力分.... Problem 1. superman [题目描述 ...

  2. NOIp2017真题模拟赛 By cellur925

    果然我还是最菜的==不接受反驳 (先考了day2喵喵喵) Day2 T1:奶酪 期望得分:100分 实际得分:100分 考察:并查集 思路:这题其实之前做过了==.思路还是比较清晰的,读入时预处理出可 ...

  3. 2017.6.11 NOIP模拟赛

    题目链接: http://files.cnblogs.com/files/TheRoadToTheGold/2017-6.11NOIP%E6%A8%A1%E6%8B%9F%E8%B5%9B.zip 期 ...

  4. 9-26模拟赛 By cellur925

    1.计数 (count.cpp/c/pas)时间限制:1s内存限制:256MB[问题描述]给出 m 个数 a[1],a[2],…,a[m]求 1~n 中有多少数不是 a[1],a[2],…,a[m]的 ...

  5. NOIp 2015真题模拟赛 By cellur925

    果然我还是最菜的==不接受反驳== Day1 T1:神奇的幻方 思路:直接模拟即可,由于当前放法只与上一放法有关系,用两个变量记录一下即可.10分钟内切掉== 预计得分:100分 实际得分:100分 ...

  6. 11.17 模拟赛&&day-2

    /* 后天就要复赛了啊啊啊啊啊. 可能是因为我是一个比较念旧的人吧. 讲真 还真是有点不舍. 转眼间一年的时间就过去了. 2015.12-2016.11. OI的一年. NOIP gryz RP++. ...

  7. 2014.11.12模拟赛【美妙的数字】| vijos1904学姐的幸运数字

    美妙的数字(number.c/.cpp/.pas) 题目描述 黄巨大认为非负整数是美妙的,并且它的数值越小就越美妙.当然0是最美妙的啦. 现在他得到一串非负整数,对于每个数都可以选择先对它做二进制非运 ...

  8. 2014.11.12模拟赛【最小公倍数】| vijos1047最小公倍数

    最小公倍数(lcm.c/.cpp/.pas) 题目描述 给定两个正整数,求他们的最小公倍数. 样例输入 28 12 样例输出 84 数据范围 对于40%数据:1<=a,b<=10^9 对于 ...

  9. 11.7NOIP模拟赛解题报告

    心路历程 预计得分:\(50 + 100 + 100\) 实际得分:\(50 + 100 +100\) T2 T3两道数据结构题美滋滋,然而写完就过去\(3h\)美滋滋 T1数学题学弟们都会做Orzz ...

  10. 11.6NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 100 = 300\) 实际得分:\(100 +100 +100 = 300\) 学OI两年终于AK了一次qwq(虽然题目炒鸡水..) 纪念一下这令人激 ...

随机推荐

  1. Dubbo Spring Cloud Motan

    跨语言统一治理.Golang,谈谈另辟蹊径的开源RPC框架Motan_搜狐科技_搜狐网 https://www.sohu.com/a/207389967_467759

  2. 5 Maven生命周期和插件

        命令行的输入往往就对应了声明周期,Maven的生命周期是抽象的,其实际行为都是由插件来完成.生命周期和插件两者协同工作,密不可分. 一.何为声明周期     Maven的生命周期就是为了对多有 ...

  3. 【LeetCode】Maximum Depth of Binary Tree

    http://oj.leetcode.com/problems/maximum-depth-of-binary-tree/ public class Solution { public int max ...

  4. 如何修改sublime3注释的颜色

    在用sublime text3编写Python2代码时总觉得注释颜色太浅了, 看起来吃力,于是就尝试去修改,和sublime text2不同, sublime text3的主题配置文件在Sublime ...

  5. jquery中的attr与prop

    http://www.cnblogs.com/Showshare/p/different-between-attr-and-prop.html

  6. Educational Codeforces Round 2 C. Make Palindrome —— 贪心 + 回文串

    题目链接:http://codeforces.com/contest/600/problem/C C. Make Palindrome time limit per test 2 seconds me ...

  7. maven项目所遇到的问题解决

    1.在Eclipse中创建Maven的Web项目时出现错误:An internal error occurred during: "Retrieving archetypes:". ...

  8. html5--3.21 课程小结与其他新增元素

    html5--3.21 课程小结与其他新增元素 学习要点 了解新增的input属性pattern 其他几个新增元素(非表单中元素,但是也放在这里讲解) 新增的input属性pattern:设定输入类型 ...

  9. List集合进行分页

    /** * @ClassName: Text2 * @Description: (集合的分页算法) * @author Luhan * @date 2017年3月16日 下午17:18:06*/pub ...

  10. 谈谈嵌套for循环的理解

    谈谈嵌套for循环的理解     说for的嵌套,先说一下一个for循环的是怎么用的.      这次的目的是为了用for循环输出一个乘法口诀表,一下就是我的一步步理解.    一.   语法:   ...