• zoj 3724 Delivery 离线处理+线段树


      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define ll long long
      6 using namespace std;
      7 int n,m,t,tol,tt;
      8 ll f[100010];
      9 ll sum[100010];
     10 struct edge{
     11     int u,v,x;
     12     ll l;
     13     edge(){}
     14     edge(int u,int v,ll l,int x):u(u),v(v),l(l),x(x){}
     15     friend bool operator<(edge a,edge b){
     16         if(a.u!=b.u) return a.u>b.u;
     17         else if(a.v!=b.v) return a.v<b.v;
     18         else return a.x<b.x;
     19     }
     20 }e[800010],te[800010];
     21 struct tree{
     22     int l,r;
     23     ll maxc,lz;
     24 }a[800010];
     25 ll ans[200010];
     26 void build(int l,int r,int k){
     27     a[k].l=l,a[k].r=r;
     28     a[k].maxc=a[k].lz=0;
     29     if(l<r){
     30        int mid=(l+r)>>1;
     31        build(l,mid,k<<1);
     32        build(mid+1,r,k<<1|1);
     33     }
     34 }
     35 void pushdown(int k){
     36     if(a[k].lz!=0){
     37        a[k<<1].maxc=max(a[k].lz,a[k<<1].maxc);
     38        a[k<<1|1].maxc=max(a[k].lz,a[k<<1|1].maxc);
     39        a[k<<1].lz=max(a[k<<1].lz,a[k].lz);
     40        a[k<<1|1].lz=max(a[k<<1|1].lz,a[k].lz);
     41        a[k].lz=0;
     42     }
     43 }
     44 void insert(int l,int r,ll c,int k){
     45     if(l<=a[k].l&&a[k].r<=r){
     46         a[k].maxc=max(a[k].maxc,c);
     47         a[k].lz=max(a[k].lz,c);
     48     }else{
     49         pushdown(k);
     50         int mid=(a[k].l+a[k].r)>>1;
     51         if(r<=mid) insert(l,r,c,k<<1);
     52         else if(l>mid) insert(l,r,c,k<<1|1);
     53         else insert(l,mid,c,k<<1),insert(mid+1,r,c,k<<1|1);
     54         a[k].maxc=max(a[k<<1].maxc,a[k<<1|1].maxc);
     55     }
     56 }
     57 ll query(int l,int r,int k){
     58     if(l<=a[k].l&&a[k].r<=r){
     59         return a[k].maxc;
     60     }else{
     61         pushdown(k);
     62         int mid=(a[k].l+a[k].r)>>1;
     63         if(r<=mid) return query(l,r,k<<1);
     64         else if(l>mid) return query(l,r,k<<1|1);
     65         else return max(query(l,mid,k<<1),query(mid+1,r,k<<1|1));
     66     }
     67 }
     68 void read(){
     69     for(int i=1;i<n;i++) scanf("%lld",&f[i]);
     70     int u,v;
     71     ll l;
     72     tol=tt=0;
     73     f[n]=(ll)1e12;
     74     for(int i=0;i<m;i++){
     75        scanf("%d%d%lld",&u,&v,&l);
     76        if(u==v) continue;
     77        if(u==n&&v==1) f[n]=min(f[n],l);
     78        if(u<v) e[tol++]=edge(u,v,l,0);
     79        else te[tt++]=edge(u,v+n,l,0);
     80     }
     81     scanf("%d",&t);
     82     for(int i=0;i<t;i++){
     83        scanf("%d%d",&u,&v);
     84        if(u<=v) e[tol++]=edge(u,v,(ll)i,1);
     85        else te[tt++]=edge(u,v+n,(ll)i,1);
     86     }
     87 }
     88 void gao(){
     89     sum[0]=0;
     90     for(int i=1;i<n;i++) sum[i]=sum[i-1]+f[i];
     91     sort(e,e+tol);
     92     build(1,n,1);
     93     for(int i=0;i<tol;i++){
     94         if(e[i].x==0){
     95             insert(e[i].v,n,sum[e[i].v-1]-sum[e[i].u-1]-e[i].l,1);
     96         }else{
     97             ans[e[i].l]=sum[e[i].v-1]-sum[e[i].u-1]-query(e[i].u,e[i].v,1);
     98         }
     99     }
    100     sort(te,te+tt);
    101     build(1,2*n-1,1);
    102     for(int i=0;i<tt;i++){
    103         int u=te[i].u,v=te[i].v-n;
    104         if(te[i].x==0){
    105             insert(v+n,2*n-1,f[n]+sum[n-1]-sum[u-1]+sum[v-1]-te[i].l,1);
    106         }else{
    107             ans[te[i].l]=f[n]+sum[n-1]-sum[u-1]+sum[v-1]-query(u,v+n,1);
    108         }
    109     }
    110 }
    111 void out(){
    112     for(int i=0;i<t;i++){
    113         printf("%lld
    ",ans[i]);
    114     }
    115 }
    116 int main(){
    117     while(~scanf("%d%d",&n,&m)){
    118         read();
    119         gao();
    120         out();
    121     }
    122     return 0;
    123 }
    zoj3724

    解题思路:

    由于题目中说短边只会走一次,所以可以发现,往前和往后是不影响的,可以分开讨论。

    然后线段树中记录的走短边的话最多可以省多少,

    离线处理,将修改和询问放一起,先按u从大到小,再按v从小到大排序,以上都一样时,修改优先。

    当u<=v时,插入的线段是[v,n],大小置为u到v的原长度-短边,询问雷同。

    当u>v时,我的做法是将线段树延伸到2*n-1处,那么线段就变为[u,v+n],那么排序和插入的做法和上面一样。

  • 相关阅读:
    SQL Server 错误日志过滤(ERRORLOG)
    SQL Server 错误日志收缩(ERRORLOG)
    (原)Max Area of Island(即连通域标记)
    (原)caffe中的conv
    (整理)plsql导入dmp文件
    (原)matlab导出oracle中blob的jpg数据到图片
    (原)faster rcnn的tensorflow代码的理解
    (原)tensorflow使用eager在mnist上训练的简单例子
    (原)DropBlock A regularization method for convolutional networks
    (原)netbeans中添加anaconda3安装的opencv
  • 原文地址:https://www.cnblogs.com/wonderzy/p/3407646.html
Copyright © 2020-2023  润新知