$$AVICII$$

hdu6521 party

原题入口

Problem - 6521 (hdu.edu.cn)

题解

对每一个位置i维护一个数组R,表示i能够到的人的最远的R,显然每个人已经认识的人是连续的,所以R是合法的。然后发现R关于i单调不减,因为如果存在i<j,且R[i]>R[j],说明存在一个操作l,r覆盖了i和j,那么i能够到的R,j也一定可以够到

答案维护就是找出区间内最大的t使得R[t]<r

$(t-l+1)*r-\sum_{i=l}^{t}R[i]$

用线段树维护求和最小值,区间修改即可

代码

  1 //对于每个人来说所认识的人必定是一段连续的区间
  2 //而且L[i],R[i]是单调递增的 
  3 //不需要吉司机线段树,因为区间修改时保证整个区间都是会被修改的 
  4 #include<bits/stdc++.h>
  5 using namespace std;
  6 #define LL long long
  7 const int MAXN=5e5+17;
  8 const int INF=1e9;
  9 inline int read(){
 10     int s=0;bool w=0;char ch=getchar();
 11     while(ch<'0'||ch>'9')w|=(ch=='-'),ch=getchar();
 12     while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
 13     return w?-s:s;
 14 }
 15 #define kd (read())
 16 int n,m;
 17 struct segment_tree{
 18     LL sm[MAXN<<2];
 19     int mn[MAXN<<2],lb[MAXN<<2];
 20     #define ls (u<<1)
 21     #define rs (u<<1|1)
 22     inline void up(int u){
 23         sm[u]=sm[ls]+sm[rs];
 24         mn[u]=min(mn[ls],mn[rs]);
 25         return ;
 26     }
 27     inline void down(int u,int l,int r){
 28         if(l==r||lb[u]==0)return ;
 29         int mid=l+r>>1;
 30     //    cout<<"u="<<u<<" "<<l<<" "<<r<<" "<<lb[u]<<endl;
 31         if(lb[u]>lb[ls]){
 32             sm[ls]=1LL*(mid-l+1)*lb[u];
 33             mn[ls]=lb[u];
 34             lb[ls]=lb[u];
 35             //cout<<ls<<" "<<l<<" "<<mid<<" "<<lb[ls]<<" "<<mn[ls]<<endl;
 36         }
 37         if(lb[u]>lb[rs]){
 38             sm[rs]=1LL*(r-mid)*lb[u];
 39             mn[rs]=lb[u];
 40             lb[rs]=lb[u];
 41         //    cout<<rs<<" "<<mid+1<<" "<<r<<" "<<lb[rs]<<" "<<mn[rs]<<endl;
 42         }
 43     //    cout<<"EDN"<<endl;
 44         return ;
 45     }
 46     void build(int u,int l,int r){
 47         lb[u]=0;
 48         if(l==r)return sm[u]=mn[u]=l,void();
 49         int mid=l+r>>1;
 50         build(ls,l,mid),build(rs,mid+1,r);
 51         return up(u),void();
 52     }
 53     int qw_pos(int u,int l,int r,int x,int y){
 54         down(u,l,r);
 55         if(r<x)return x-1;
 56         if(l>y)return x-1;
 57         if(mn[u]>=y)return x-1;
 58         if(l==r)return l;
 59         int mid=l+r>>1;
 60         if(mn[rs]<y)return qw_pos(rs,mid+1,r,x,y);
 61         else return qw_pos(ls,l,mid,x,y);
 62     }
 63     LL qw_sm(int u,int l,int r,int x,int y){
 64         down(u,l,r);
 65         if(l>=x&&r<=y)return sm[u];
 66         int mid=l+r>>1;LL res=0;
 67         if(x<=mid)res+=qw_sm(ls,l,mid,x,y);
 68         if(y>=mid+1)res+=qw_sm(rs,mid+1,r,x,y);
 69         return res;
 70     }
 71     void modify(int u,int l,int r,int x,int y,int w){
 72         down(u,l,r);
 73         if(l>=x&&r<=y){
 74             mn[u]=lb[u]=w;
 75             sm[u]=1LL*(r-l+1)*w;
 76             return ;
 77         }
 78         int mid=l+r>>1;
 79         if(x<=mid)modify(ls,l,mid,x,y,w);
 80         if(y>=mid+1)modify(rs,mid+1,r,x,y,w);
 81         return up(u),void();
 82     }
 83 }T;
 84 int main(){
 85     freopen("data.in","r",stdin);
 86     freopen("std.out","w",stdout);
 87     while(~scanf("%d%d",&n,&m)){
 88         T.build(1,1,n);
 89         for(int i=1,x,y;i<=m;++i){
 90             x=kd,y=kd;
 91             LL sm=0;
 92             int t=T.qw_pos(1,1,n,x,y);
 93             //cout<<"t="<<t<<endl;
 94             if(t>=x)sm=1LL*(t-x+1)*y-T.qw_sm(1,1,n,x,t);
 95             printf("%lld\n",sm);
 96             if(t>=x)T.modify(1,1,n,x,t,y);
 97         }
 98     }
 99     return 0;
100 }
View Code

 

posted @ 2022-07-04 11:29  bootpuss  阅读(21)  评论(0编辑  收藏  举报