bzoj4293 [PA2015]Siano

  首先需要意识到这一点:生长速度快的植物,无论进行多少次操作,其高度一定大于等于生长速度慢的植物。于是可以先把植物生长速度进行排序,建立线段树,有两种标记,一种标记表示经历了多少时间,另一种为覆盖标记,一开始先把时间标记打上两个询问的时间差,然后用二分查询找到第一个高度>=询问值的位置i,然后使用线段树统计答案,并把i到n覆盖掉,注意标记更新顺序。

  

  代码

  

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #define N 5000010
  5 using namespace std;
  6 int l[N],r[N],e[N];
  7 long long v1[N],v2[N],S[N],s[N],a,b,ta,n,m,i,ma[N];
  8 void build(int x,int a,int b)
  9 {
 10     int m;
 11     l[x]=a;r[x]=b;v2[x]=-1;v1[x]=0;
 12     if (b-a>1)
 13     {
 14         m=(a+b)>>1;
 15         build(2*x,a,m);
 16         build(2*x+1,m,b);
 17         s[x]=s[2*x]+s[2*x+1];
 18     }
 19     else
 20         s[x]=e[b];
 21 } 
 22 void clean(int x)
 23 {
 24     if (v2[x]>=0)
 25     {
 26         ma[x]=v2[x];
 27         S[x]=(r[x]-l[x])*v2[x];
 28         v2[2*x]=v2[x];v1[2*x]=0;
 29         v2[2*x+1]=v2[x];v1[2*x+1]=0;
 30         v2[x]=-1;
 31     }
 32     if (v1[x])
 33     {
 34         ma[x]+=v1[x]*e[r[x]];
 35         S[x]=S[x]+v1[x]*s[x];
 36         v1[2*x]+=v1[x];
 37         v1[2*x+1]+=v1[x];
 38         v1[x]=0;
 39     }
 40 }
 41 void gao(int x,int a,int b,long long c)
 42 {
 43     int m;
 44     clean(x);
 45     if ((a<=l[x])&&(r[x]<=b))
 46     {
 47         v2[x]=c;
 48         return;
 49     }
 50     m=(l[x]+r[x])>>1;
 51     if (a<m) gao(2*x,a,b,c);
 52     if (m<b) gao(2*x+1,a,b,c);
 53     clean(2*x);clean(2*x+1);
 54     S[x]=S[2*x]+S[2*x+1];
 55     ma[x]=ma[2*x+1];
 56 }
 57 long long query(int x,int a,int b)
 58 {
 59     long long ans=0;
 60     int m;
 61     clean(x);
 62     if ((a<=l[x])&&(r[x]<=b))
 63         return S[x];
 64     m=(l[x]+r[x])>>1;
 65     if (a<m) ans+=query(2*x,a,b);
 66     if (m<b) ans+=query(2*x+1,a,b);
 67     return ans;
 68 }
 69 int find(int x,long long y)
 70 {
 71     clean(x);
 72     if (r[x]-l[x]==1)
 73     {
 74         if (ma[x]>=y)
 75         return r[x]-1;
 76         else
 77         return r[x];
 78     }
 79     clean(2*x);clean(2*x+1);
 80     if (ma[2*x]>=y)
 81     return find(2*x,y);
 82     else
 83     return find(2*x+1,y);
 84 }
 85 int main()
 86 {
 87     scanf("%lld%lld",&n,&m);
 88     for (i=1;i<=n;i++)
 89         scanf("%d",&e[i]);
 90     sort(e+1,e+1+n);
 91     build(1,0,n);
 92     
 93     for (i=1;i<=m;i++)
 94     {
 95         scanf("%lld%lld",&a,&b);
 96         v1[1]+=a-ta;
 97         int L=1,R=n,mid;
 98         
 99         R=find(1,b);
100     //    printf("%d
",R);
101         
102         if (R<n)
103         {
104             printf("%lld
",query(1,R,n)-b*(n-R));
105             gao(1,R,n,b);
106         }
107         else
108             printf("0
");
109         ta=a;
110     }    
111 }
原文地址:https://www.cnblogs.com/fzmh/p/5384685.html