zoukankan      html  css  js  c++  java
  • BZOJ2388: 旅行规划

    n<=1e5个数,m<=1e5个操作:区间加,查区间最大的1~i号点的和。

    第一次见到nsqrt(n)logn能过1e5的。。然而跑得很慢

    普通数据结构感觉难下手,那就分块。先处理前缀和数组。一次修改,实际上把一段前缀和加上了一个等差数列,然后把这区间后面的前缀和加上某个固定数字,也可以看成另一个等差数列。等差数列叠加依然是等差数列,那就考虑整块打上一个A,B标记表示这一块加上首项(A+B)公差B的等差数列后的结果。

    假设一块里的第i个数是Si,那如果i比j优(j>i),就有

    $s_i+i*B+A>s_j+j*B+A$

    整理得

    $frac{s_i-s_j}{j-i}>B$

    嘿嘿,每个块维护个凸包就搞定了

    实测块大小取150跑得比较快。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stdlib.h>
      4 #include<algorithm>
      5 #include<math.h>
      6 //#include<time.h>
      7 //#include<iostream>
      8 using namespace std;
      9 
     10 int n,m,q;
     11 #define maxn 100011
     12 #define maxm 561
     13 #define LL long long
     14 int bel[maxn],tot; LL shou[maxm],cha[maxm],a[maxn],tu[maxm][maxm];
     15 double calc(int i,int j) {return 1.0*(a[i]-a[j])/(j-i);}
     16 void maketu(int x)
     17 {
     18     int l=(x-1)*m+1,r=min(x*m,n);
     19     tu[x][0]=0;
     20     for (int i=l;i<=r;i++)
     21     {
     22         while (tu[x][0]>1 && calc(tu[x][tu[x][0]-1],tu[x][tu[x][0]])>=calc(tu[x][tu[x][0]],i)) tu[x][0]--;
     23         tu[x][++tu[x][0]]=i;
     24     }
     25 }
     26 void down(int x)
     27 {
     28     if (!shou[x] && !cha[x]) return;
     29     int l=(x-1)*m+1,r=min(x*m,n);
     30     for (int i=l,cnt=1;i<=r;i++,cnt++) a[i]+=shou[x]+cha[x]*cnt;
     31     shou[x]=cha[x]=0;
     32 }
     33 void modifysingle(int x,int y,LL s,LL v)
     34 {
     35     if (x>y) return;
     36     down(bel[x]);
     37     for (int i=x,cnt=1;i<=y;i++,cnt++) a[i]+=s+cnt*v;
     38     maketu(bel[x]);
     39 }
     40 void modify(int x,int y,LL v)
     41 {
     42     if (bel[x]==bel[y]) 
     43     {
     44         modifysingle(x,y,0,v);
     45         LL s1=(y-x+1)*v;
     46         modifysingle(y+1,min(bel[y]*m,n),(y-x+1)*v,0);
     47         for (int i=bel[y]+1;i<=tot;i++) shou[i]+=s1;
     48     }
     49     else
     50     {
     51         LL s1=(bel[x]*m-x+1)*v,s2=((bel[y]-1)*m-x+1)*v,s3=(y-x+1)*v;
     52         for (int i=bel[x]+1;i<bel[y];i++) shou[i]+=s1,cha[i]+=v,s1+=m*v;
     53         modifysingle(x,bel[x]*m,0,v);
     54         modifysingle((bel[y]-1)*m+1,y,s2,v);
     55         modifysingle(y+1,min(bel[y]*m,n),s3,0);
     56         for (int i=bel[y]+1;i<=tot;i++) shou[i]+=s3;
     57     }
     58 }
     59 LL querysingle(int x,int y)
     60 {
     61     down(bel[x]);
     62     LL ans=-1e18;
     63     for (int i=x;i<=y;i++) ans=max(ans,a[i]);
     64     maketu(bel[x]);
     65     return ans;
     66 }
     67 LL query(int x,int y)
     68 {
     69     if (bel[x]==bel[y]) return querysingle(x,y);
     70     else
     71     {
     72         LL ans=-1e18;
     73         for (int i=bel[x]+1;i<bel[y];i++)
     74         {
     75             int L=1,R=tu[i][0];
     76             while (L<R)
     77             {
     78                 const int mid=(L+R)>>1;
     79                 if (calc(tu[i][mid],tu[i][mid+1])>=cha[i]) R=mid;
     80                 else L=mid+1;
     81             }
     82             ans=max(ans,a[tu[i][L]]+shou[i]+(tu[i][L]-(i-1)*m)*cha[i]);
     83         }
     84         ans=max(ans,querysingle(x,bel[x]*m));
     85         ans=max(ans,querysingle((bel[y]-1)*m+1,y));
     86         return ans;
     87     }
     88 }
     89 int main()
     90 {
     91     scanf("%d",&n);
     92     m=min(150,n);
     93     for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1;
     94     tot=bel[n];
     95     
     96     for (int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]+=a[i-1];
     97     for (int i=1;i<=tot;i++) maketu(i);
     98     
     99     scanf("%d",&q);
    100     int id,x,y,z;
    101     while (q--)
    102     {
    103         scanf("%d",&id);
    104         if (id)
    105         {
    106             scanf("%d%d",&x,&y);
    107             printf("%lld
    ",query(x,y));
    108         }
    109         else
    110         {
    111             scanf("%d%d%d",&x,&y,&z);
    112             modify(x,y,z);
    113         }
    114     }
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    poj 1035 (Spell checker )
    poj 3080 (暴力 strstr)
    kmp 模版
    匈牙利算法模版
    poj 1274 The Perfect Stall (最大匹配)
    hdu 1083 Courses(二分图 )
    pku 3363(内部测试赛)
    Linux 下联网脚本文件
    Qt 多国语言
    引用和引用参数
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8042631.html
Copyright © 2011-2022 走看看