洛谷P2190 小Z的車廂
阿新 • • 發佈:2018-11-25
題目描述
小Z的家鄉有一列在環形鐵軌上行駛的火車,共停靠 n 個站(1 號站到 n 號站順時針排列)。
眾所周知,春運是一件非常可怕的事情。不幸的是,小Z是鐵路公司的員工,現在他收到了 m 條除夕凌晨的訂票申請,每個申請 (x,y,z) 表示有 z 個人要從 x 號站順時針坐到 y 號站,同時,當火車停靠到x號站時,所有要在x站上車的人都會上車,所有要在x號站下車的人都會下車。
由於始發站不確定,現在小Z想知道至少需要分配給這列火車多少節車廂(每節車廂可容納 36 人)才能順利完成該鐵路運輸,希望你幫幫他。
輸入輸出格式
輸入格式:
第一行包含兩個整數 n,m。
接下來 m 行,每行包含三個整數 x,y,z。
輸出格式:
第一行包含一個整數,表示至少需要分配給這列火車的車廂數。
輸入輸出樣例
輸入樣例#1:
3 2 1 2 36 2 3 36
輸出樣例#1:
1
輸入樣例#2:
4 2 1 2 36 4 3 36
輸出樣例#2:
2
洛谷說這是一道模擬題,不過我覺得這是在坑人
我想到了三個解法(題解上說的差分我不是很懂):
解法1
直接暴力模擬,時間O(NM)這個顯然是不行的
解法2
如果你很強,對演算法掌握的很好的話,就可以直接用險段樹做
利用lazy延遲修改,並且查詢最大值,比賽的時候一般不用
這樣很太複雜而且不容易除錯,但是不暴力
時間是O(mlogn+logn),不過常數和記憶體都很大
我雖然會不過不想打了
解法3
樹狀陣列+差分
這一題我們利用樹狀陣列來維護差分
1修改:
如果x<y
那麼我們就給點x +z(update(x,z))
給點y -z(update(y,-z))
如果x>y
就update(x,z),update(1,z),update(y,-z)
很好的處理首尾相接
最後
求出每一個數的字首和,找出最大的,處理一下就行了
程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<string>
#include<set>
#include<ctime>
#define lowbit(x) x&(-x)
using namespace std;
inline int read(){
int x=0,f=0;char s=getchar();
while(!isdigit(s))f|=s=='-',s=getchar();
while( isdigit(s))x=(x<<1)+(x<<3)+s-48,s=getchar();
return !f?x:-x;
}
inline void print(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10+'0');
}
const int N=1e6+20;
int n,m,a[N];
void update(int x,int t){//給點x加t
while(x<=n){
a[x]+=t;
x+=lowbit(x);
}
}
int getsum(int x){//求點x的字首和
int sum=0;
while(x>0){
sum+=a[x];
x-=lowbit(x);
}
return sum;
}
int main(){
n=read();m=read();
int x,y,z;
for(int i=1;i<=m;i++){
x=read();y=read();z=read();//差分修改
if(x<y)update(x,z),update(y,-z);
else update(x,z),update(1,z),update(y,-z);
}
int maxx=0;
for(int i=1;i<=n;i++)//求最大值
maxx=max(maxx,getsum(i));
if(maxx%36==0)maxx/=36;
else maxx=maxx/36+1;
print(maxx);//輸出
return 0;
}