[NOIP2013]车站分级 解题报告
妈蛋这道普及组水(神)题搞了我非常久。
一、
首先一个非常显然的事情就是每一个火车告诉了站与站之间的等级关系,所以拓扑求最长路。
可是发现暴力建边的话最坏能够达到500*500,所以时间复杂度有O(MN2)≈2.5∗108,常数相当小。
。数据水成狗,所以绝对能够过的。
二、
所以我就想到了bitset,把每辆火车做成一个长N的布尔向量。经过为1,不经过为0,第一个车站的左边和最后一个车站的右边补1,。
然后对于每一个车站,把全部它所在的位为1的向量都&起来,然后扫一遍向量连边。
这样做的时间复杂度能够用long long模拟bitset的时间复杂度来预计。就是O(MN264)≈107,常数更小了。实际跑起来事实上跟10^6差点儿相同。
三、
然后我看了一个大神的代码,发现原来是有正儿八经的O(NM)的做法的。
我们发现车站之间是比較麻烦的,所以考虑对偶转换!!
我们这样来考虑。比方说我们设火车经过的最低等级的车站为火车的等级,那么火车的等级数=车站的等级数?
依照上面的定义,火车的等级数自然是小于等于车站的等级数的。而假设一个车站不是不论什么一辆火车的等级,那么就意味着它能够下降或上升它自己的等级直到它是不论什么一辆火车的等级呢?
可是这种前提是每一辆车站都至少有一辆火车经过。所以自然我们仅仅要加一辆经过全部车站的火车就能够了。
这种话。我们仅仅须要求出火车的等级就可以了!
可是火车的等级怎么求呢?假设不存在一个车站使得两辆火车都经过它,那么显然这两辆火车之间是没有直接的等级关系的;而假设它们有交的话,那么显然在交集部分经过很多其它车站的火车的等级应该是更低的。由于低等级的车站会经过全部高等级的车站经过的车站!
一定要注意的地方:
①拓扑求最长路的时候是要求Max!!
②一定要对拍!
code(bitset):
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
inline void in(int &x){
char c=getchar();
x=0;
while(c<'0'||c>'9')c=getchar();
for(;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0');
}
int l[1005],r[1005];
#include<bitset>
bitset<1005> be[1005],btmp;
int next[1000005],ptr[1005],succ[1000005];
int stack[1005],level[1005],ru[1005];
int main(){
freopen("level2013.in","r",stdin);
freopen("level_TA.out","w",stdout);
int n,m,i,j,stop,s;
in(n),in(m);
for(i=m;i--;){
in(s);
in(l[i]);
for(--s;--s;){
in(stop);
be[i][stop]=1;
}
in(r[i]);
for(j=l[i];j;--j)be[i][j]=1;
for(j=r[i];j<=n;++j)be[i][j]=1;
}
int etot=1;
for(i=n;i;--i){
btmp.set();
for(j=m;j--;)
if(l[j]<=i&&i<=r[j]&&be[j][i]){
//cout<<"Get:"<<j<<endl;
btmp&=be[j];
}
for(j=n;j;--j)
if(~btmp[j]){
next[etot]=ptr[i],ptr[i]=etot,succ[etot++]=j;
//cout<<i<<"->"<<j<<":"<<ptr[i]<<"->"<<next[etot-1]<<endl;
++ru[j];
}
}
int top=0;
for(i=n;i;--i)
if(ru[i]==0){
stack[top++]=i;
level[i]=1;
//cout<<"First into stack:"<<i<<endl;
}
int nowlevel;
while(top--){
nowlevel=level[stack[top]];
//cout<<"----"<<stack[top]<<"-----\n";
for(i=ptr[stack[top]];i;i=next[i]){
level[succ[i]]=max(level[succ[i]],nowlevel+1);
//cout<<i<<":"<<nowlevel+1<<"->"<<succ[i]<<endl;
if(--ru[succ[i]]==0)stack[top++]=succ[i];
}
}
printf("%d\n",*max_element(level+1,level+n+1));
}
code(对偶转换):
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
inline void in(int &x){
char c=getchar();
while(c<'0'||c>'9')c=getchar();
x=0;
for(;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0');
}
int num[1005][1005],stop[1005][1005];
int stack[1005];
int next[1000005],ptr[1005],succ[1000005],ru[1005],etot=1;
int level[1005];
inline void addedge(int u,int v){
next[etot]=ptr[u],ptr[u]=etot,++ru[v],succ[etot++]=v;
}
int main(){
freopen("level2013.in","r",stdin);
freopen("level2013.out","w",stdout);
int n,m,i,j,k,tmp;
in(n),in(m);
++m;
for(i=n;i;--i)num[0][i]=stop[0][i]=i;
stop[0][0]=n;
for(i=m;--i;){
in(stop[i][0]);
for(j=1,k=1;j<=stop[i][0];++j)
for(in(stop[i][j]);k<stop[i][j];++k)
num[i][k]=j-1;
--j;
while(k<=n)num[i][k++]=j;
}
int l,r;
for(i=m;i--;)
for(j=i;j--;){
l=max(stop[i][1],stop[j][1])-1;
r=min(stop[i][stop[i][0]],stop[j][stop[j][0]]);
if(l<=r)
if(num[i][r]-num[i][l]>num[j][r]-num[j][l])addedge(i,j);
else if(num[i][r]-num[i][l]<num[j][r]-num[j][l])addedge(j,i);
}
int top=0;
for(i=m;i--;)
if(!ru[i]){
stack[top++]=i;
level[i]=1;
}
int nowlevel;
while(top--){
nowlevel=level[stack[top]]+1;
for(i=ptr[stack[top]];i;i=next[i]){
level[succ[i]]=max(level[succ[i]],nowlevel);
if(!--ru[succ[i]])stack[top++]=succ[i];
}
}
printf("%d\n",*max_element(level,level+m));
}
[NOIP2013]车站分级 解题报告的更多相关文章
- [NOIP2013 花匠] 新人解题报告
本来按照老师的要求,我学OI的第一份解题报告应是在寒假完成的关于数据结构的基础题,但由于身体原因当时未能完成,那么就在省选赛前临时写几篇吧…… 题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿 ...
- NOIp2013 车站分级 【拓扑排序】By cellur925
题目传送门 我们注意到,题目中说:如果这趟车次停靠了火车站 x,则始发站.终点站之间所有级别大于等于火车站x的都必须停靠.有阶级关系,满满的拓扑排序氛围.但是,如果我们按大于等于的关系连,等于的情况就 ...
- noip2013 车站分级
题目描述 一条单向的铁路线上,依次有编号为 1, 2, …, n1,2,…,n的 nn个火车站.每个火车站都有一个级别,最低为 11 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟 ...
- 题解【洛谷P1983】[NOIP2013]车站分级
题面 题解 不难想到拓扑排序 于是每一个等级高的向等级低的连一条边 考虑拓扑排序过程中的分层 对于每个点进行分层 于是答案就是这些点中的最大层数 然后就会RE 发现我们多连了一些重复的边 用一个标记数 ...
- 【NOIP2013 普及组】车站分级
[NOIP2013 普及组]车站分级 一.题目 [NOIP2013 普及组]车站分级 时间限制: 1 Sec 内存限制: 128 MB 提交: 3 解决: 0 [提交][状态][讨论版] 题目描述 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- $HNOI\ 2010$ 解题报告
HNOI 2010 解题报告 0. HNOI2010 AC代码包下载地址 注: 戳上面的标题中的'地址' 下载 代码包, 戳下面每一题的文件名 可进入 题目链接. 每一题 对应代码的文件名 我在 每一 ...
- 洛谷P1983车站分级
洛谷\(P1983\)车站分级(拓扑排序) 目录 题目描述 题目分析 思路分析 代码实现 题目描述 题目在洛谷\(P1983\)上 题目: 一条单向的铁路线上,依次有编号为 \(1, 2, -, ...
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
随机推荐
- python-生成器即send()用法
参考链接: http://www.mamicode.com/info-detail-2399245.html 作者首先介绍了生成器的作用:是为了让程序员可以更简单的编写用来产生值的序列的代码,然后又介 ...
- 洛谷 P2015 二叉苹果树 && caioj1107 树形动态规划(TreeDP)2:二叉苹果树
这道题一开始是按照caioj上面的方法写的 (1)存储二叉树用结构体,记录左儿子和右儿子 (2)把边上的权值转化到点上,离根远的点上 (3)用记忆化搜索,枚举左右节点分别有多少个点,去递归 这种写法有 ...
- ecnu 1244
SERCOI 近期设计了一种积木游戏.每一个游戏者有N块编号依次为1 ,2,-,N的长方体积木. 对于每块积木,它的三条不同的边分别称为"a边"."b边"和&q ...
- 设计模式 - 组合模式(composite pattern) 迭代器(iterator) 具体解释
组合模式(composite pattern) 迭代器(iterator) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考组合模式(composit ...
- p2p項目夭折,有種蛋蛋的憂傷。。
在高考完的暑假就在跟杰哥讨论怎样实现的校内p2p文件共享,就在今天.我们无奈的宣布差点儿夭折. 上图是測试图. 那时候的思路已经完好.就是:"学生上传共享文件到咱们工作室的server. ...
- 昼猫笔记 从此告别复杂代码--JavaScript
昼猫笔记--给你带来不一样的笔记 不止是笔记 更多的是思考 大家好,我是一只来自喵星的前端初学者,由于我们喵星人科技较为落后,昼猫从今天开始带着使命来到地球学习前端知识. 从今天开始,猫猫我就从Jav ...
- react-native signatures do not match the previously installed version;
原因:手机上已经安装过打包后的apk应用,与真机调试无法共存. 解决办法:删除手机上已经安装过的apk应用.
- Supervisor 的安装与配置教程
简介 Supervisor是一个进程控制系统. 它是一个C/S系统(注意: 其提供WEB接口给用户查询和控制), 它允许用户去监控和控制在类UNIX系统的进程. 它的目标与launchd, daemo ...
- route---设置Linux内核中的网络路由表
route命令用来显示并设置Linux内核中的网络路由表,route命令设置的路由主要是静态路由.要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现. 在L ...
- Android的SQLite的增删查改
原创作品,允许转载,转载时请务必声明作者信息和本声明.http://www.cnblogs.com/zhu520/p/8343675.html 本人小白,那个大神看到有问题可指出,谢谢.... 一:s ...