标签:alt 考试 题解 return class scan scanf 技术 src
考试的时候刚了很久.
还是没做出来.
看完了题解才恍然大悟.
贴一发丑陋的两个log常数巨大代码
#include <bits/stdc++.h> using namespace std; const int N=200010; const long long INF=1e18; int n,m,k,lg[N]; long long s[N],f[N][18],g[N][18]; pair<int,int> a[N]; void UPD(int i,int j,long long r[N][18]){ r[i][j]=(i+(1<<(j-1))<=k?min(r[i][j-1],r[i+(1<<(j-1))][j-1]):r[i][j-1]); } long long ask(int x,int y,long long r[N][18]){ return x>y?INF:min(r[x][lg[y-x+1]],r[y-(1<<lg[y-x+1])+1][lg[y-x+1]]); } long long hhdask(int x,int y,int dpos){ if (x>y) return INF; int be=lower_bound(a+1,a+k+1,make_pair(x,0))-a; int en=lower_bound(a+1,a+k+1,make_pair(y+1,0))-a-1; int mid=lower_bound(a+1,a+k+1,make_pair(dpos,0))-a; long long rmin=ask(mid,en,f)-s[dpos-1]; long long lmin=ask(be,mid-1,g)+s[dpos-1]; return min(lmin,rmin); } bool check(int x,int e,long long v,int po){//close interval long long t=hhdask(x-e+po,x+e+po-1,x); if (!po||t!=v) return t>v; return hhdask(x-e+1,x+e-1,x)>v; } signed main(){ lg[1]=0; for (int i=2; i<=200000; ++i) lg[i]=lg[i>>1]+1; scanf("%d%d",&n,&m); for (int i=1; i<n; ++i){ int x; scanf("%d",&x); s[i]=s[i-1]+x; } for (int i=1; i<=m; ++i){ long long ans=0; scanf("%d",&k); for (int i=1; i<=k; ++i) scanf("%d%d",&a[i].first,&a[i].second); sort(a+1,a+k+1); for (int i=1; i<=k; ++i) f[i][0]=a[i].second+s[a[i].first-1],g[i][0]=a[i].second-s[a[i].first-1]; for (int i=1; i<18; ++i) for (int j=1; j<=k; ++j) UPD(j,i,f),UPD(j,i,g); for (int i=1; i<=k; ++i){ //find l limit int ll=a[i].first,rr=a[i].first; for (int l=1,r=a[i].first,mid=(l+r)>>1; l<=r; mid=(l+r)>>1) if (check(mid,a[i].first-mid,a[i].second+s[a[i].first-1]-s[mid-1],0)) ll=mid,r=mid-1; else l=mid+1; //find r limit for (int l=a[i].first,r=n,mid=(l+r)>>1; l<=r; mid=(l+r)>>1) if (check(mid,mid-a[i].first,a[i].second+s[mid-1]-s[a[i].first-1],1)) rr=mid,l=mid+1; else r=mid-1; ans+=rr-ll+1; } printf("%lld\n",ans); } }
感觉这题应该是可以一个log做的,
就是有些难写,需要仔细考虑一下.
标签:alt 考试 题解 return class scan scanf 技术 src
原文地址:https://www.cnblogs.com/Yuhuger/p/8969846.html