題目鏈結
題目翻譯
題面大學生\(joi\)君要坐公交車上學。他的家和學校都在\(ioi\)市內,他住在\(1\)號結點,大學在\(n\)號結點。
\(ioi\)市有\(m\)輛公交車,每輛公交車每天只開一次,從特定的時刻在某個站點出發,在特定的時刻到達某個站點,不能在中途上下車,且時間跨度不會超過一天。
\(joi\)每天要換乘巴士去學校,他換乘的時間可以忽略不計,即:如果要乘坐在\(time_i\)時刻從\(pos_i\)站點出發的公交車,那麼他只需要在\(time_i\)時刻之前(包含這個時刻)到達站點\(pos _i\)。他可以重複走過乙個車站。
\(joi\)要去學校上\(q\)天課,每天上課的時間各不相同,現在他想知道,他每天最晚什麼時候從家裡出發不會遲到。
輸入第一行包括兩個整數\(n,m\)
接下來\(m\)行,每行\(4\)個整數,\(a_i,b_i,x_i,y_i\)表示第\(i\)輛公交車在時刻\(x_i\)從站點\(a_i\)出發,在時刻\(y_i\)到達\(b_i\)。時刻是從午夜零點開始經過了多少毫秒(這個沒啥用吧)。
下一行包括乙個整數\(q\),表示上學的天數
接下來\(q\)行,每行乙個整數\(l_j\)表示第\(j\)天必須要在時刻\(l_j\)之前到校。
輸出\(q\)行,\(q\)個整數,表示答案,如果不能按時到校,輸出\(-1\)
資料範圍
\(2<=n<=100000\)
\(1<=m<=300000\)
\(0<=x_i
\(1<=q<=100000\)
\(0<=l_i<24*60*60*1000\)
樣例輸入1
5 6
1 2 10 25
1 2 12 30
2 5 26 50
1 5 5 20
1 4 30 40
4 5 50 70410
3060
100
輸出1-1510
30
輸出23 8
1 2 1 5
1 3 0 1
1 3 2 8
2 3 2 3
2 3 3 4
2 3 4 5
2 3 5 6
2 3 6 763
4567
8
輸出2000
112
小言(基本上是我的碎碎念,可以skip
這是一道布置在某谷上的作業題。
翻完之後同學告訴我\(joi\)啊呸,我錯亂了,是
\(loj\)上有翻譯,心態大崩。
只能說練習了日文能力和熟練使用翻譯軟體的能力?
哼哼,\(loj\)的翻譯就是逐字逐句譯出來的而已,沒有靈魂(說得好像我自己的翻譯就很優秀一樣
但是某谷採納譯文之後居然不給署名,氣抖冷,原創保護什麼時候才能站起來。
題目解析
法一:貪心亂搞
由於我太菜了,不能像其他大佬那樣很快地想到遞推什麼的,於是上來先亂搞。
貪心地想,我們先走到達時間小的邊不容易遲到。
而顯然\(l\)越大,條件越寬鬆,所以把詢問從小到大處理。
由於我們要求的東西是\(1\)的時間,這個不方便搜尋,所以從\(n\)出發。
設\(d[i]\)表示為了不遲到,從\(n\)出發到達\(i\)的最晚時間,那麼答案就是\(d[1]\)
更新答案的時候,沿著邊走,記錄下到達這個點的最大時間是多少,和這個點公交車的到達時間比較,如果公交車到得比我要求的最大時間還要晚,那就不能走這條邊了。
之前把詢問從小到大排序,可以發現前面\(l\)較小求出來的\(d[i]\)可以用來更新\(l\)更大時的\(d[i]\),你想,之前上學時間早的時候的出發時間肯定不會比上學時間晚的時間更晚,即正確性是有保障的,只是可能不會那麼優秀,所以取\(max\)就好了。
所以一條邊只會經過一次,之前用這條邊更新了的答案在\(d[i]\)裡面,後面可以直接用,不用再走一遍這條邊,複雜度是\(o(m)\)。
法二:dp遞推
發現啥時候到校和坐的最後一輛公交車息息相關。
設\(f[i]\)表示坐第\(i\)輛公交車最晚幾點出發,\(g[i]\)表示到達第\(i\)個點最晚幾點出發
將所有公交車拆成出發和到達,按時間從小到大排序,\(f,g\)相互更新:
出發:用\(g\)更新\(f\),相當於統計答案:到校的最晚時間等價於坐上最後那輛公交車的最晚時間。如果這輛公交車的起點是\(1\),那麼坐上這輛車的最晚時間就是\(f[i]=t[i]\),否則坐上這輛車的最晚時間取決於到達起點的允許最晚出發時間,也就是\(f[i]=g[u[i]]\)。
到達:用\(f\)更新\(g\):\(g[v[i]]=max(g[v[i]],f[i])\),如果可以坐上車\(i\),那麼在\(f[i]\)出發也可以到達\(g[v[i]]\)
由於是按照時間從小到大排序,如果大於\(t[i]\)的\(g[u[i]]\)對答案不會產生影響——這個時候\(g[u[i]]\)還沒有更新到那麼大,\(g[u[i]]\)要麼比\(t[i]\)小,要麼沒有值(無解,因為不可能從起點飛到\(u[i]\)來吧)
詢問和出發的處理方式是一樣的,詢問的答案就是對應的\(f\)
有個小細節:排序時,如果時間一樣,先到達,再出發,因為一樣的時間,可以到達之後在馬上接著出發。
►code view ver.1
#include#include#include#include#includeusing namespace std;
#define ll long long
#define n 100005
#define m 300005
#define del 100000
#define inf 0x3f3f3f3f
int rd()
while(c>='0'&&c<='9')
return f*x;}/*
實際上是l時刻從n出發 求到達1的最晚時刻(也就是在路上花費時間最小
把詢問從小到大處理 顯然l大的邊答案會更大
而且乙個更大的l的答案可以用小的l產生的答案更新 所以每條邊只會走1次
d[i]表示從n出發 到達i的最大時刻
*/ int n,m;
int d[n],ans[n];
struct node;
vectorg[n];
struct pp[m];
struct nodequery[n];
bool cmp(p l,p r)
bool cmp2(node l,node r)
while(c>='0'&&c<='9')
return f*x;
}int n,m;
int f[m<<1]/*詢問也在這*/,g[n];
struct node;
vectorquery;
bool cmp(node p,node q)
int main()
int q=rd();
for(int i=1;i<=q;i++)
sort(query.begin(),query.end(),cmp);
memset(g,-1,sizeof(g));
for(int i=0;ielse//到達
g[x]=max(g[x],f[id]);
} for(int i=1;i<=q;i++)
printf("%d\n",f[m+i]);
return 0;
}
年輪蛋糕JOI2014Final
試題描述 joi 君馬上要和妹妹 joi 子和 joi 美一起吃小吃。今天的小吃是他們三個人都很喜歡的年輪蛋糕。年輪蛋糕是像下圖一樣呈圓筒形的蛋糕。為了把蛋糕分給三個人,joi 君必須沿著半徑方向切 3 刀,從而把蛋糕分成三塊。然而,由於年輪蛋糕硬得像實木一樣,要讓刀切進去並不簡單。因此,這個年輪蛋...
CQOI2014 萬用字元匹配
點此看題 弱化版 ahoi2005 病毒檢測 先把 當成分割符,這樣帶萬用字元的串就被劃分成了若干個小串,我們對於每乙個小串在去另乙個串中匹配。對於每乙個小串,以?為分割符,將它插入ac text ac自動機中,標記終止節點,把在小串中的終止位置存在ed x ed x ed x 中 型別為vec t...
bzoj3507 Cqoi2014 萬用字元匹配
我們將題目輸入的那個含萬用字元的串,記為 萬用字元串 下面的檔名記為 檔名 檔名 數量很少可以依次查詢。我們先將 萬用字元串 以 為界,將 萬用字元串 分解,得到若干子串,記為 通配子串 我們將每個 通配子串 各建立乙個 ac自動機。而有的 通配子串 可能含 萬用字元,我們將再次按 為界,分解這個 ...