P8856 [POI2002]火车线路
[POI2002]火车线路
题目描述
某列火车从 \(1\) 号城市出发,前往编号为 \(C\) 的城市。该火车有 \(S\) 个座位,现在有 \(R\) 个车票订购需求。
一个订购由 \(O,D,N\) 三个整数组成,表示从起点站 \(O\) 到目标站 \(D\) 需要订购 \(N\) 个座位。
如果在该订购范围内有能满足的空座位,就称该订购可以被满足,否则就不可以。
请你按订购给出顺序处理,判断是否可以满足该订购需求。
输入格式
第一行为三个整数 \(C,S,R\)。
接下来 \(R\) 行,每行为三个整数 \(O,D,N\),分别表示每一个预定。
输出格式
对第 \(i\) 个预定,如果能满足,输出 T,否则输出 N。
样例 #1
样例输入 #1
4 6 4
1 4 2
1 3 2
2 4 3
1 2 3
样例输出 #1
T
T
N
N
提示
数据范围:\(1 \le C,S,R \le 60000\)。
跟NOIP有一年的题一样
首先 可以转换成区间最小值问题
对于每次询问 判断[o,d]区间中的所有数是否都大于等于n
即只用判断最小值即可 也就是动态区间修改最小值查找问题
就可以用segment tree解决
还有就是有个细节 查询不能查[o,d] 而是要查[o,d-1]
因为到了d站(这次询问的终点站)已经下车了 不需要位置了
好久没打线段树了操作的细节要熟悉
比如说pushdown操作对minn add都要进行
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int c,s,r;
struct tree{
int l,r,sum,mul,add,minn;
}tr[60005*4];
void pushup(int p)
{
tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
tr[p].minn=min(tr[p<<1].minn,tr[p<<1|1].minn);
return ;
}
void pushdown(int p)
{
tr[p<<1].add+=tr[p].add;
tr[p<<1|1].add+=tr[p].add;
tr[p<<1].minn+=tr[p].add;
tr[p<<1|1].minn+=tr[p].add;
tr[p].add=0;
}
void build(int p,int l,int r)
{
tr[p].l=l,tr[p].r=r;
if(l==r)
{
tr[p].minn=s;
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
void modify(int p,int l,int r,int add)
{
if(l<=tr[p].l&&r>=tr[p].r)
{
tr[p].minn+=add;
tr[p].add+=add;
return ;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1;
if(l<=mid)modify(p<<1,l,r,add);
if(r>mid)modify(p<<1|1,l,r,add);
pushup(p);
}
int query(int p,int l,int r)
{
if(l<=tr[p].l&&r>=tr[p].r)
{
return tr[p].minn;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1;
int minx=INT_MAX;
if(l<=mid)minx=min(minx,query(p<<1,l,r));
if(r>mid)minx=min(minx,query(p<<1|1,l,r));
return minx;
}
signed main()
{
ios::sync_with_stdio(false);
cin>>c>>s>>r;
build(1,1,c);
while(r--)
{
int o,d,n;
cin>>o>>d>>n;
d--;//!!!
// cout<<query(1,o,d)<<"\n";
if(query(1,o,d)>=n)
{
cout<<"T\n";
modify(1,o,d,-n);
}
else cout<<"N\n";
}
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号