ZOJ 3724 Delivery(离线线段树)
来源:互联网 发布:网络借条平台 编辑:程序博客网 时间:2024/05/02 02:35
题意:N个点,对于每个点i,都有一条连向i+1的有向边,另外有M条其他的有向边,有Q个询问(U,V)求U到V的最短路。
当U<V的时候,很好处理查询下U到V范围内哪条边节省的时间多就可以了。U>V的处理方法很相似。分两种情况,分别离线处理一次就可以了。
//#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <vector>#include <algorithm>#include <queue>#include <set>#include <map>using namespace std;typedef long long LL;typedef pair<int,int> PII;#define INF (1LL<<60)#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=100005;LL A[N],sum[N],ans[N*2];struct OP{ int st,ed,w; OP(){} OP(int st,int ed,int w) : st(st),ed(ed),w(w) {}};bool cmpST(const OP &A,const OP &B){ return A.st<B.st;}bool cmpED(const OP &A,const OP &B){ return A.ed<B.ed;}vector<OP> QA,QB;vector<OP> RA,RB;struct Segtree{ LL mx[N*4]; void PushUp(int ind) { mx[ind]=max(mx[LL(ind)],mx[RR(ind)]); } void build(int lft,int rht,int ind) { mx[ind]=-INF; if(lft!=rht) { int mid=MID(lft,rht); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); } } void updata(int pos,LL valu,int lft,int rht,int ind) { if(lft==rht) mx[ind]=max(mx[ind],valu); else { int mid=MID(lft,rht); if(pos<=mid) updata(pos,valu,lft,mid,LL(ind)); else updata(pos,valu,mid+1,rht,RR(ind)); PushUp(ind); } } LL query(int st,int ed,int lft,int rht,int ind) { if(st<=lft&&rht<=ed) return mx[ind]; else { LL mx1=-INF,mx2=-INF; int mid=MID(lft,rht); if(st<=mid) mx1=query(st,ed,lft,mid,LL(ind)); if(ed> mid) mx2=query(st,ed,mid+1,rht,RR(ind)); return max(mx1,mx2); } }}seg;int main(){ // freopen("in.txt","r",stdin); int n,m,Q; while(scanf("%d%d",&n,&m)!=EOF) { QA.clear(); QB.clear(); RA.clear(); RB.clear(); int len1=0,len2=0; sum[1]=0; for(int i=2;i<=n;i++) scanf("%lld",&A[i]); for(int i=2;i<=n;i++) sum[i]=A[i]+sum[i-1]; for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a<b) { if(sum[b]-sum[a]<c) continue; else RA.push_back(OP(a,b,(sum[b]-sum[a])-c)); } else { LL tmp=sum[b]+(sum[n]-sum[a]); RB.push_back(OP(b,a,tmp-c)); } } scanf("%d",&Q); for(int i=0;i<Q;i++) { int a,b; scanf("%d%d",&a,&b); if(a<b) QA.push_back(OP(a,b,i)); else if(a>b) QB.push_back(OP(b,a,i)); else ans[i]=0; } seg.build(1,n,1); sort(QA.begin(),QA.end(),cmpED); sort(RA.begin(),RA.end(),cmpED); len1=(int)QA.size(); len2=(int)RA.size(); int ind=0; for(int i=0;i<len1;i++) { while(ind<len2&&RA[ind].ed<=QA[i].ed) { seg.updata(RA[ind].st,RA[ind].w,1,n,1); ind++; } LL tmp=seg.query(QA[i].st,QA[i].ed,1,n,1); tmp=max(tmp,0LL); ans[QA[i].w]=sum[QA[i].ed]-sum[QA[i].st]-tmp; } seg.build(1,n,1); sort(QB.begin(),QB.end(),cmpST); sort(RB.begin(),RB.end(),cmpST); len1=(int)QB.size(); len2=(int)RB.size(); ind=0; for(int i=0;i<len1;i++) { while(ind<len2&&RB[ind].st<=QB[i].st) { seg.updata(RB[ind].ed,RB[ind].w,1,n,1); ind++; } LL tmp=seg.query(QB[i].ed,n,1,n,1); ans[QB[i].w]=sum[n]-(sum[QB[i].ed]-sum[QB[i].st])-tmp; } for(int i=0;i<Q;i++) printf("%lld\n",ans[i]); }return 0;}
- ZOJ 3724 Delivery(离线线段树)
- zoj 3724 离线+线段树
- ZOJ 3724 Delivery(树状数组+离线处理)
- ZOJ-3800:Calculation(线段树+离线)
- zoj 3800 Calculation(离线 + 线段树)
- zoj 3633 Alice's present(离线+线段树)
- zoj-3633 Alice's present 离线线段树
- [ZOJ 3633]Alice's present 离线分块/线段树
- zoj 3724 线段树
- ZOJ - 3469 Food Delivery(区间DP)
- zoj 3469 Food Delivery (区间DP)
- ZOJ 3469 Food Delivery(区间DP)
- ZOJ-3469-Food Delivery(区间DP)
- (ZOJ 3469)Food Delivery 区间DP
- zoj 3469 Food Delivery(区间dp)
- HDU 4031 Attack(离线+线段树)
- Hdu 5200 Trees (离线线段树)
- hdu4638 Group(离线线段树)
- Ovirt VDSM -- Feature Branding
- 【学习笔记】Algorithmes with numbers(1)
- java I/O流之文件操作
- SDL介绍
- Java 自定义Annotation
- ZOJ 3724 Delivery(离线线段树)
- 15th Training
- 揭开Socket编程的面纱
- cpu怎样区别指令和数据
- 求两个字符串的最长公共子序列
- DFS专攻:HDU 1312与COJ 1061
- Java的执行顺序,笔试遇到的问答题(做完这题执行顺序不会再错)
- Android Layout XML属性
- 有12个球,外形相同,其中一个小球的质量与其他11个不同,给一个天平,需要几次把这个小球找出来并且求出这个小球是比其他的轻还是重