1. 程式人生 > >NOIP2013 普及組 車站分級

NOIP2013 普及組 車站分級

題意

一條單向的鐵路線上,依次有編號為 1, 2, …, n 的 n 個火車站。每個火車站都有一個級別,最低為 1 級。現有若干趟車次在這條線路上行駛,每一趟都滿足如下要求:如果這趟車次停靠了火車站 x,則始發站、終點站之間所有級別大於等於火車站 x 的都必須停靠。
(注意:起始站和終點站自然也算作事先已知需要停靠的站點)
例如,下表是 5 趟車次的執行情況。其中,前 4 趟車次均滿足要求,而第 5 趟車次由於停靠了 3 號火車站(2 級)卻未停靠途經的 6 號火車站(亦為 2 級)而不滿足要求。
這裡寫圖片描述
現有 m 趟車次的執行情況(全部滿足要求),試推算這 n 個火車站至少分為幾個不同的級別。



[Solution]
這題可以根據車分級,也可以根據點分級,寫起來都差不多
(只是根據車分級跑的快,根據點分級跑得慢……)

先考慮點:
先說如何分級:如果兩個點(A和B)被同一輛車經過,並且車停在了A,沒有停在B,那麼A的等級一定比B高.

那麼根據這個,把等級高的向等級低的連一條邊,表示它們不能在同一個等級.這個做法還是很好實現的,而且程式碼也很短.只需在讀入時記錄停留的點和沒停留的點,把停留的點向所有沒停留的點連一條邊就好了.

這就是根據點分級的做法了,只要算出不同等級的數量,就得到了答案

然後就是怎麼求的問題了,很容易發現,構造出的圖一定是一個有向無環圖(DAG),所以當然是選擇dp求了.每個點的等級都是所有兒子中的最大值加1.

由於資料很水,這種方法卡下常數就過了…..

如果有了點的做法,其實車的做法也很接近了:
把車的等級定為這輛車上等級最低的點.對於兩輛車(A,B),假如它們的路線相交,在相交路徑上停靠點少的車的等級比另一輛高.這樣車也有等級了,然後把車當成點,再按點的演算法計算就好了.

但是這樣好像不對,車的等級為什麼能代表點的等級呢?

可以看下面的圖:
這裡寫圖片描述
(黑點表示停靠的點)

A車的等級為2,B為1.但是它們上面都有和它們等級不同的點;不過,這也沒關係,因為取了這輛車中等級最高的點,所以不用關心其它點.
(但是必須再加一輛從1到n停靠所有點的車,保證沒有點的等級為0

這樣的話和上一種其實差不多,但是,車之間比較大小隻需要用字首和維護區間和,就可以讓比較大小的複雜度變為O

(1),但是點之間比較大小的複雜度必須要O(n)

所以,想到一種不怎麼樣的演算法後,再仔細想想,可能就想出整解了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int M=1005;
struct node {
    int st,ed;
    int sum[M];
    bool operator > (const node &t) const {
        int mst=max(st,t.st);
        int med=min(ed,t.ed);
        if (mst>med) return false;
        return sum[med]-sum[mst-1]>t.sum[med]-t.sum[mst-1];
    }
} way[M];
vector <int> e[M];
int dp[M];
int rec(int x) {
    if (dp[x]) return dp[x];
    int res=0;
    for (int i=0;i<e[x].size();++i) {
        res=max(res,rec(e[x][i]));
    }
    return dp[x]=res+1;
}
int main() {
    int n,m;
    cin>>n>>m;
    for (int i=1;i<=m;++i) {
        int s;
        scanf("%d",&s);
        for (int j=1;j<=s;++j) {
            int x;
            scanf("%d",&x);
            if (j==1) way[i].st=x;
            else if (j==s) way[i].ed=x;
            way[i].sum[x]=1;
        }
        for (int j=way[i].st;j<=way[i].ed;++j) way[i].sum[j]+=way[i].sum[j-1];
    }
    way[0].st=0,way[0].ed=n;
    for (int i=1;i<=n;++i) way[0].sum[i]=way[0].sum[i-1]+1;
    for (int i=0;i<=m;++i) {
        for (int j=0;j<=m;++j) {
            if (i==j) continue;
            if (way[i]>way[j]) e[i].push_back(j);
        }
    }
    int res=0;
    for (int i=0;i<=m;++i) {
        res=max(res,rec(i));
    }
    cout<<res<<endl;
    return 0;
}

相關推薦

NOIP2013 普及 車站分級

題意 一條單向的鐵路線上,依次有編號為 1, 2, …, n 的 n 個火車站。每個火車站都有一個級別,最低為 1 級。現有若干趟車次在這條線路上行駛,每一趟都滿足如下要求:如果這趟車次停靠了火車站 x,則始發站、終點站之間所有級

NOIP 普及 車站分級 [拓撲排序][線段樹優化連邊][虛點優化]

一條單向的鐵路線上,依次有編號為1, 2, &hellip;, n的n個火車站。每個火車站都有一個級別,最低為1級。現有若干趟車次在這條線路上行駛,每一趟都滿足如下要求:如果這趟車次停靠了火車站x,則始發站、終點站之間所有級別大於等於火車站x的都必須停靠。(注意:起始站和終點站自然也算作事先已知需要

洛谷 P1982 小朋友的數字(NOIp2013普及T3)

文件 ret vijos 觀察 個數 color 符號 朋友 麻煩 題目描述 有 n 個小朋友排成一列。每個小朋友手上都有一個數字,這個數字可正可負。規定每個小朋友的特征值等於排在他前面(包括他本人)的小朋友中連續若幹個(最少有一個)小朋友手上的數字之和的最大值。 作為這些

表達式求值(NOIP2013 普及第二題)

tool ber 算術表達式 class 整數 括號 給定 編程 解釋 描述 給定一個只包含加法和乘法的算術表達式,請你編程計算表達式的值。 格式 輸入格式 輸入僅有一行,為需要你計算的表達式,表達式中只包含數字、加法運算符“+”和乘法運算符“*”,且沒有括號,所有參與運算

NOIP2013普及 題解

T1  計數問題 題目描述 試計算在區間 1 到 n 的所有整數中,數字 x(0 ≤ x ≤ 9)共出現了多少次?例如,在 1 到 11 中,即在 1、2、3、4、5、6、7、8、9、10、11 中,數字 1 出現了 4 次。 輸入輸出格式 輸入格式:輸入檔名為 count

NOIP2013普及P2】表示式求值(NKOJ2500)題解

【NOIP2013普及組P2】表示式求值 Time Limit:10000MS  Memory Limit:128000K Total Submit:37 Accepted:19 Case Time

【蒻爆了的NOIP系列--普及複賽】(4)NOIP2013普及複賽題解

這只是一個作業,如果有幫到您的,我只能說。。。這不科學。。。 ————————————華麗的分割線———————————— 第一題: 神似noip2016t1… 貌似就資料範圍和輸入方式

luogu1981 表示式求值(NOIP2013普及第2題)

時空限制    1000ms/128MB 題目描述 給定一個只包含加法和乘法的算術表示式,請你程式設計計算表示式的值。 輸入輸出格式 輸入格式: 一行,為需要你計算的表示式,表示式中只包含數字、加法運算子“+”和乘法運算子“×”,且沒有括號,所有參與運算的數字均

NOIP2013普及 T2 表示式求值

OJ地址:洛谷P1981 CODEVS 3292 正常寫法是用棧 1 #include<iostream> 2 #include<algorithm> 3 #inclu

1180: [NOIP2013普及]表示式求值

輸入僅有一行,為需要你計算的表示式,表示式中只包含數字、加法運算子“+”和乘法運算子“*”,且沒有括號,所有參與運算的數字均為0到231-1之間的整數。輸入資料保證這一行只有0~ 9、+、*這12種字元。0≤表示式中加法運算子和乘法運算子的總數≤100000

noip2013普及解題報告

第一題:記數問題 題目描述 Description 試計算在區間1到n的所有整數中,數字x(0≤x≤9)共出現了多少次?例如,在1到11中,即在1、2、3、4、5、6、7、8、9、10、11中,數字1出現了4次。 輸入描述 Input Descriptio

luogu1983【2013普及車站分級(拓撲排序)

每一趟列車,沒停靠的站的分級一定比停靠了的小,我們從停靠的站向沒停靠的站建一條有向邊,顯然是個DAG,我們進行拓撲排序,看分成幾個階段(把棧內所有上次的點都刪掉算一次。)。就是答案。 #include

【用膝蓋寫程式碼系列】(5):NOIP2013普及複賽詳解

有人問我為什麼2013在2014之後? 那是因為。。。。。。你醜(這句劃掉) 2013年難啊! …… 第一題:計數問題 題面簡述:試計算在區間 1 到 n 的所有整數中,數字 x(0 ≤

luogu1980 計數問題(NOIP2013普及第1題)

時空限制    1000ms/128MB 題目描述 試計算在區間 1 到 n 的所有整數中,數字 x(0 ≤ x ≤ 9)共出現了多少次?例如,在 1 到 11 中,即在 1、2、3、4、5、6、7、8、9、10、11 中,數字 1 出現了 4 次。 輸入輸出格式

noip普及2013 車站分級(luogu P1983)

eof 矩陣 oid har 一個 org pac 題目 style 原題鏈接:https://www.luogu.org/problem/show?pid=1983 題目大意:每個車站有一個權值,每一車次始發站與終點站之間如果有不停靠的點,那麽它的權值一定比停靠的點的權值

題解:車站分級(2013普及

這道題可以暴力可以拓撲排序 甚至還可以差分約束???? 原諒我一開始沒看出來可以差分約束 這是暴力做法 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using nam

【NOIP 2013 普及車站分級

【題目】 題目描述: 一條單向的鐵路線上,依次有編號為 1,2,…, 的  個火車站。每個火車站都有一個級別,最低為 1 級。現有若干趟車次在這條線路上行駛,每一趟都滿足如下要求:如果這趟車次停靠了火車站 x,則始發站、終點站之間所有級別大於等於火車站 x 的都必須停靠。

[Noip2013] 車站分級

復制 ans 一個 輸入輸出格式 個數 cdn fin efi ace 題目描述 一條單向的鐵路線上,依次有編號為 1,2,…,n1, 2, …, n 1,2,…,n的 nn n個火車站。每個火車站都有一個級別,最低為 111

noip2013題解 普及

這次整體題目個人認為不是非常難,但是想取得高分並不容易。 接下來是我的個人分析(包含ak程式碼) 1.計數問題 首先,第一眼看到這個題目我就驚呆了。因為做過。看了看資料範圍,比較小,每個數字最多6位,1000000個,6000000次秒過是沒有太大的問題的。 只要將每一個數

[NOIP2013]車站分級

algorithm namespace 站點 ios span ron ons col getc 原題傳送門 這道題根據題意,能得出該結論: ·一條線路經過的站點,停靠站點等級一定大於未停靠的站點 又因為輸入保證所有的車次都滿足要求,所以滿足偏序集關系。