"BZOJ4167" Forever Bamboo Shoots picking
The puzzle: We consider how many point pairs (A, B) satisfy the difference between A and B. is the smallest of [b]. Think it is random data, so the number of points may be very small, measured is O (n) level, then we know there are so many possible to contribute to the point pair, how to find out?
Consider chunking, because all numbers are in [1,n], and we can preprocess the entire block to the minimum difference of all numbers for each block. Then enumerate each point from right to left, and then enumerate all the blocks on it, and if the difference between the block and the current number is smaller than the previous one, then the violence is swept through the block. At the same time, we need to know if we already have such a pair, which is completely contained by the current point pair and has a smaller difference. This can be done in a tree-like array.
Finally, we get all the point pairs, the problem becomes a line on the axis to select the intersection of K-cross segments, so that the segment weights and minimum. Run a DP on the line.
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include < algorithm>using namespace Std;const int maxn=60010;int n,m,b,cnt,minn;int s[maxn],v[maxn],p[maxn];int cls[250][ Maxn],f[2][maxn],to[500000],next[500000],head[maxn],val[500000];int Rd () {int Ret=0,f=1;char gc=getchar (); while (GC < ' 0 ' | | Gc> ' 9 ') {if (gc== '-') F=-f;gc=getchar ();} while (gc>= ' 0 ' &&gc<= ' 9 ') ret=ret*10+gc-' 0 ', Gc=getchar (); return ret*f;} int z (int x) {return x>0?x:-x;} void Updata (int x,int val) {for (int i=x;i<=n;i+=i&-i) s[i]=min (s[i],val);} int query (int x) {int i,ret=1<<30;for (i=x;i;i-=i&-i) ret=min (Ret,s[i]); return ret;} void Test (int a,int b) {int c=z (V[b]-v[a]), A++,b++,minn=min (Minn,c), if (query (b) <=c) return, Updata (b,c); To[cnt]=a, val[cnt]=c,next[cnt]=head[b],head[b]=cnt++;} int main () {//freopen ("bz4168.in", "R", stdin), N=rd (), M=rd (), B=ceil (sqrt (n)); int i,j,k,last;for (i=0;i<n;i++) v[i] =rd (); memset (Cls,0x3f,sizeof (CLS)); memset (s,0x3f,sizeof (s));for (i=0;i<n;i+=b) {for (j=i;j<i+b&&j<n;j++) p[v[j]]=1;for (last=-1<<30,j=1;j<=n;j++) cls[ I/b][j]=min (Cls[i/b][j],j-last), Last=p[j]?j:last;for (last=1<<30,j=n;j>=1;j--) cls[i/B][j]=min (Cls[i/B] [J],last-j], Last=p[j]?j:last;for (j=i;j<i+b&&j<n;j++) p[v[j]]=0;} memset (head,-1,sizeof (head)); for (i=n-1;i>=0;i--) {minn=1<<30;for (j=i+1;j<i/b*b+b&&j<n;j+ +) if (V[j]!=v[i]&&z (V[j]-v[i]) <minn) test (I,J); for (j=i/b+1;j*b<n;j++) if (Cls[j][v[i]]<minn) for (k =j*b;k<j*b+b&&k<n;k++) if (V[k]!=v[i]&&z (V[k]-v[i]) <minn) test (i,k);} for (k=1;k<=m;k++) {for (i=0;i<=n;i++) f[k&1][i]=1<<30;for (i=1;i<=n;i++) {f[k&1][i]=f[k& 1][i-1];for (J=head[i];j!=-1;j=next[j]) f[k&1][i]=min (f[(k&1) ^1][to[j]-1]+val[j],f[k&1][i]);}} printf ("%d\n", F[m&1][n]); return 0;}
BZOJ4167 Forever Bamboo Shoots picking block + tree-like array