[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的矩阵,矩阵中的每个位置上都长着一棵树 ...
随机推荐
- C++ priority_queue的使用 & Java PriorityQueue
刚刚那道BST的题目,也用到了priority_queue,那是那个没有定义比较函数. 那么下面这个,就要定义比较函数. 它的模板声明带有三个参数,priority_queue<Type, Co ...
- Swift的闭包,枚举,类和结构体
闭包(Closures) 使用过其它语言的应该对代码块并不陌生,Swift中的闭包与C,OC中的Block相似. 表示自包括的函数代码块.能够在代码中传递和使用. 而且能够捕获和存储上下文的变量以及常 ...
- 算法导论————KMP
[例题传送门:caioj1177] KMP模版:子串是否出现 [题意]有两个字符串SA和SB,SA是母串,SB是子串,问子串SB是否在母串SA中出现过.如果出现过输出第一次出现的起始位置和结束位置,否 ...
- js易错点总结及 常见面试的坑
最近在研究Javascript发现了其中一些比较灵异的事情.有点让人感到无语比如: var arr = [], arr2 = {}; console.log(typeof(arr) === typeo ...
- 101.C++继承三种权限
三种访问权限 public:可以被任意实体访问 protected:只允许子类及本类的成员函数访问 private:只允许本类的成员函数访问 三种继承特点 1.public继承不改变基类成员的访问权限 ...
- 《读书报告 – Elasticsearch入门 》----Part II 深入搜索(2)
第十三章 全文检索 这一章开始介绍 全文检索 :怎样对全文字段(full-text fields)进行检索以找到相关度最高的文档. 全文检索最重要的两个方面是: 相关度(Relevance) 根据文档 ...
- Android studio 导入PullToRefresh
1.新建一个Android项目,下载好Android-PullToRefresh-master,并解压,找到library文件夹,我把他放在C:\import目录下,下面的都是根据箭头一步一步的点击即 ...
- vue 实现文本域还剩多少字符
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- POJ Oulipo KMP 模板题
http://poj.org/problem?id=3461 Oulipo Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4 ...
- [Chromium文档转载,第005章]Calling Mojo from Blink
For Developers > Design Documents > Mojo > Calling Mojo from Blink Variants Let's as ...