zjoi[ZJOI2018]胖
Posted yinwuxiao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zjoi[ZJOI2018]胖相关的知识,希望对你有一定的参考价值。
题解:
因为n,m很大
所以复杂度应该是和m相关的
考虑到每个点的影响区间是连续的
就很简单了
区间查询最小值线段树维护(st表也可以)
然后注意一下不要重复算一个就可以了
max函数用template<class T> 不能与原来min重名
代码:
#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; #define ll long long #define IL inline #define rint register int #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) const int N=3e5; const ll INF=1e18; const int N2=1e7; ll dis[N],sum1[N],sum2[N]; int n,m,cnt; struct re{ int a; ll b; }; vector<int> ve; ll data1[N2],data2[N2]; int ls[N2],rs[N2]; char ss[1<<27],*A=ss,*B=ss; IL char gc() { return (A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++); } template<class T>void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c==‘-‘) f=-1; x=c^48; while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } char sr[1<<24],z[20]; int C=-1,Z; template <class T> void wer(T x) { if (x<0) sr[++C]=‘-‘,x=-x; while (z[++Z]=x%10+48,x/=10); while (sr[++C]=z[Z],--Z); sr[++C]=‘ ‘; } template<class T> T MAX(T x,T y) { if (x>y) return(x); else return(y); } template<class T> T MIN(T x,T y) { if (x<y) return(x); else return(y); } IL void swap(int &x,int &y) { int tmp=x; x=y; y=tmp; } void clear() { cnt=0; for (int i=0;i<ve.size();i++) { int x=ve[i]; data1[x]=INF; data2[x]=INF; ls[x]=0; rs[x]=0; } ve.clear(); } void updata(int x) { data1[x]=MIN(data1[ls[x]],data1[rs[x]]); data2[x]=MIN(data2[ls[x]],data2[rs[x]]); } void change(int &x,int h,int t,int pos,ll k) { if (!x) x=++cnt; ve.push_back(x); if (h==t) { data1[x]=MIN(data1[x],sum1[pos-1]+k); data2[x]=MIN(data2[x],sum2[pos]+k); return; } int mid=(h+t)/2; if (pos<=mid) change(ls[x],h,mid,pos,k); else change(rs[x],mid+1,t,pos,k); updata(x); } ll query1(int x,int h,int t,int h1,int t1) { if (!x) return(INF); if (h1<=h&&t<=t1) return(data1[x]); ll ans=INF; int mid=(h+t)/2; if (h1<=mid) ans=query1(ls[x],h,mid,h1,t1); if (mid<t1) ans=MIN(ans,query1(rs[x],mid+1,t,h1,t1)); return(ans); } ll query2(int x,int h,int t,int h1,int t1) { if (!x) return(INF); if (h1<=h&&t<=t1) return(data2[x]); ll ans=INF; int mid=(h+t)/2; if (h1<=mid) ans=query2(ls[x],h,mid,h1,t1); if (mid<t1) ans=MIN(ans,query2(rs[x],mid+1,t,h1,t1)); return(ans); } IL ll check1(int h,int t,int x) { h=MAX(h,1); t=MIN(t,n); return(query2(1,1,n,h,t)-sum2[x]); } IL ll check2(int h,int t,int x) { h=MAX(h,1); t=MIN(t,n); return(query1(1,1,n,h,t)-sum1[x-1]); } int main() { read(n); read(m); rep(i,1,n-1) read(dis[i]); rep(i,1,n-1) sum1[i]=dis[i],sum1[i]+=sum1[i-1]; dep(i,n-1,1) sum2[i]=dis[i],sum2[i]+=sum2[i+1]; rep(i,0,N2-1) data1[i]=INF,data2[i]=INF; rep(i,1,m) { int x,y; ll ans=0,z; read(x); vector<re> ve1; ve1.push_back((re){0,0}); clear(); int root=0; rep(j,1,x) { read(y); read(z); change(root,1,n,y,z); ve1.push_back((re){y,z}); } rep(j,1,x) { int y=ve1[j].a; ll z=ve1[j].b; int h=y,t=n; while (h<t) { int mid=(h+t+1)/2; ll jl=sum1[mid-1]-sum1[y-1]+z; if (MIN(check1(y+1,mid,mid),check2(mid,2*mid-y-1,mid))>jl&& check2(2*mid-y,2*mid-y,mid)>=jl) h=mid; else t=mid-1; } ans+=t-y; h=1,t=y; while (h<t) { int mid=(h+t)/2; ll jl=sum1[y-1]-sum1[mid-1]+z; if (MIN(check2(mid,y-1,mid),check1(2*mid-y+1,mid,mid))>jl&& check1(2*mid-y,2*mid-y,mid)>jl) t=mid; else h=mid+1; } ans+=y-h+1; } wer(ans); } fwrite(sr,1,C+1,stdout); return 0; }
以上是关于zjoi[ZJOI2018]胖的主要内容,如果未能解决你的问题,请参考以下文章