HDU 5861 Road 线段树区间更新单点查询
題目鏈接:
http://acm.split.hdu.edu.cn/showproblem.php?pid=5861
Road
Time Limit: 12000/6000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)
問題描述
There are n villages along a high way, and divided the high way into n-1 segments. Each segment would charge a certain amount of money for being open for one day, and you can open or close an arbitrary segment in an arbitrary day, but you can open or close the segment for just one time, because the workers would be angry if you told them to work multiple period.
We know the transport plan in the next m days, each day there is one cargo need to transport from village ai to village bi, and you need to guarantee that the segments between ai and bi are open in the i-th day. Your boss wants to minimize the total cost of the next m days, and you need to tell him the charge for each day.
(At the beginning, all the segments are closed.)
輸入
Multiple test case. For each test case, begins with two integers n, m(1<=n,m<=200000), next line contains n-1 integers. The i-th integer wi(1<=wi<=1000) indicates the charge for the segment between village i and village i+1 being open for one day. Next m lines, each line contains two integers ai,bi(1≤ai,bi<=n,ai!=bi).
輸出
For each test case, output m lines, each line contains the charge for the i-th day.
樣例
sample input
4 3
1 2 3
1 3
3 4
2 4
sample output
3
5
5
題意
有n個村莊排成一行,中間n-1條路,每條路開啟的花費是a[i]每天,你可以選擇每條路的開啟時間和關閉時間,但是路關閉之后就不能再開啟。現在告訴你接下來的m天的行程,每天會有一輛貨車從u到v,你需要保證貨車經過的道路必須是開啟的。問每天的最小花費。
題解
用線段樹求出使用到每條道路的最早時間和最晚時間(這就是我們需要設置的開啟時間和關閉時間了)。然后以天數作為數組,再建一顆線段樹,根據沒條道路的開放時間[mi,ma]去區間更新,然后單點查詢求每一天的花費是多少。
代碼
這里用的是一種不需要打懶惰標記的方法,并且由于是單點查詢,所以只需要往下更新,不用回溯回來。
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; #define X first #define Y second #define mkp make_pair #define lson (o<<1) #define rson ((o<<1)|1) #define mid (l+(r-l)/2) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++)typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII;const int INF=0x3f3f3f3f; const LL INFL=0x3f3f3f3f3f3f3f3fLL; const double eps=1e-8; const double PI = acos(-1.0);//start----------------------------------------------------------------------const int maxn=2e5+10;int road[maxn];//這里maxv,minv是一顆線段樹,sumv是另一顆線段樹,偷懶寫在一起了 int maxv[maxn<<2],minv[maxn<<2]; int sumv[maxn<<2];int ql,qr,_v,_v2; void update(int o,int l,int r,int type) {if(ql<=l&&r<=qr) {if(type==-1) {maxv[o]=max(maxv[o],_v);minv[o]=min(minv[o],_v);} else {sumv[o]+=_v2;}} else {if(ql<=mid) update(lson,l,mid,type);if(qr>mid) update(rson,mid+1,r,type);}}int _p,_ma,_mi,_sum; void query(int o,int l,int r,int add,int ma,int mi) {if(l==r) {_ma=max(ma,maxv[o]);_mi=min(mi,minv[o]);_sum=add+sumv[o];} else {if(_p<=mid) query(lson,l,mid,add+sumv[o],max(ma,maxv[o]),min(mi,minv[o]));else query(rson,mid+1,r,add+sumv[o],max(ma,maxv[o]),min(mi,minv[o]));} }void init() {clr(sumv,0);clr(maxv,-1);clr(minv,0x3f); }int main() {int n,m;while(scanf("%d%d",&n,&m)==2&&n) {init();for(int i=1; i<=n-1; i++) scanf("%d",&road[i]);///求每條路開放的最早和最遲時間for(int i=1; i<=m; i++) {int u,v;scanf("%d%d",&u,&v);if(u>v) swap(u,v);v--;ql=u,qr=v,_v=i;update(1,1,n-1,-1);}for(int i=1; i<=n-1; i++) {_p=i,_ma=-1,_mi=INF;query(1,1,n-1,0,_ma,_mi);// printf("%d,%d\n",_mi,_ma);if(_mi>_ma) continue;ql=_mi,qr=_ma,_v2=road[i];update(1,1,m,1);}///求每天的花費是多少for(int i=1; i<=m; i++) {_p=i,_sum=0;query(1,1,m,0,_ma,_mi);printf("%d\n",_sum);}}return 0; }//end-----------------------------------------------------------------------轉載于:https://www.cnblogs.com/fenice/p/5785322.html
總結
以上是生活随笔為你收集整理的HDU 5861 Road 线段树区间更新单点查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于java反射机制(基础篇)
- 下一篇: 刺激(codevs 1958)