Preliminary study on "algorithm" CDQ Division and Treatment

Source: Internet
Author: User

CDQ Division is a powerful weapon to deal with data structure problems, in layman's words, it can replace a layer of data structure, so as to reduce the code difficulty and the role of constants, the disadvantage is that it must be offline.

CDQ Division can be used to deal with partial order problems and slope optimization DP problems.

Different from ordinary division, the answer to the left interval of the CDQ division has contributed to the right interval, the most classic example is the merging sort for reverse order.

Let's talk about the problem of partial order:

The two-dimensional partial order is essentially the same as the merge sort, not much mentioned.

Three-dimensional partial order: the first dimension of direct ordering, the second dimension with CDQ, the third dimension with a tree-like array.

In particular, the CDQ is divided into partial order. Because our first dimension is already sorted, there is absolutely no case of the first dimension of the first Werbe right interval in the left interval.

Then recursively after the left and right interval, the left and the the interval are sorted by the second dimension, then we can count the left interval of the contribution of the elements of the interval, because the second dimension of the right interval is ordered, so you can sweep the right interval, each find the largest left interval of the second dimension is less than the current enumeration to the second dimension of the Maintain a third dimension with a tree array and update the answer.

Four-dimensional partial order: in fact, can use CDQ Division of the CDQ division of the way, just to change the above bit into a CDQ division of the good, according to this, n-dimensional partial order can be done is not it?

$\geq$ Five-dimensional partial order: ... can be done, but the complexity of the heavens. Five-dimensional partial order upward is not as $o (n^2) $ ...

The basic flow of CDQ for partial order problem:

If $l==r$ is returned.

Divide and treat left interval, divide and conquer right interval.

The contribution of the left interval to the right interval is counted.

Eliminate the contribution of bit (the set of CDQ is not required).

Three-dimensional partial-order code:

#include <iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<algorithm>using namespacestd;Const intmaxn=500010;structpoi{intA, B, C, CNT, ans;} V[MAXN], TMP[MAXN];intN, K, Tott;intANS[MAXN], CNT[MAXN], TREE[MAXN], Q[maxn];inlinevoidReadint&k) {    intf=1; k=0;CharC=GetChar ();  while(c<'0'|| C>'9') c=='-'&& (f=-1), c=GetChar ();  while(c<='9'&& c>='0') k=k*Ten+c-'0', c=GetChar (); K*=F;} InlineBOOLCMP2 (Poi A, poi b) {returna.b<b.b| | (A.b==b.b && a.c<B.C);} InlineBOOLCMP (Poi A, poi b) {returna.a<b.a| | (A.A==B.A &&CMP2 (A, b));} InlinevoidUpdateintXintDelta) { for(; x<=k;x+=x&-x) tree[x]+=Delta;}; InlineintQueryintx) {intsum=0; for(; x;x-=x&-x) sum+=tree[x];returnsum;}voidSolveintLintR) {    if(L==R)return; intMid= (l+r) >>1; Solve (L, mid); Solve (mid+1, R); Sort (v+l, v+mid+1, CMP2); Sort (v+mid+1, v+r+1, CMP2); intL1=l, l2=mid+1;  while(l2<=r) { while(L1<=mid && v[l1].b<=v[l2].b) Update (V[L1].C, v[l1].cnt), + +L1; V[l2].ans+=query (V[L2].C); ++L2; }     for(inti=l;i<l1;i++) Update (V[I].C,-v[i].cnt);}intMain () {read (n); read (k);  for(intI=1; i<=n;i++) Read (TMP[I].A), read (tmp[i].b), read (TMP[I].C); Sort (tmp+1, tmp+1+N, CMP);  for(intI=1, j=1; i<=n;i=j) {v[++tott]=Tmp[i];  while(tmp[i].a==tmp[j].a && tmp[i].b==tmp[j].b && tmp[i].c==tmp[j].c && j<=N) J+ +, v[tott].cnt++; } Solve (1, Tott);  for(intI=1; i<=tott;i++) cnt[v[i].ans+v[i].cnt-1]+=v[i].cnt;  for(intI=0; i<n;i++) printf ("%d\n", Cnt[i]);}
View Code

Slope optimization DP with CDQ can also remove a layer of data structure, but the wording and partial order slightly different, according to the above practice may be more than one $log$ for sorting.

when we use the left interval to update the right interval, it is clear that the things that need to be sorted are not the same . at this point we cannot simply sort by time and then divide the rule.

At this time there is a very meow meow practice. First by the right sort of the equation, each time we divide, we can use $o (n) $ time to divide the number $\leq mid$ to the left,$> mid$ points to the right, but if you start by number, it is impossible to do $o (N) $ time to divide the slope to the left and right sides.

Each time we first recursive to the left interval, each time we exit the interval according to the horizontal axis of the sorting, and we started by the equation to the right of the order, so the left interval after recursion is the left interval is ordered, the right interval is ordered by the right of the equation, then we can $o (n) $ The slope optimization DP is done with the monotone queue.

The basic flow of slope optimization DP with CDQ Division:

If L==r is returned.

The left interval by the number of $\leq mid$ to the left, $>mid$ to the right.

Divide and conquer left interval.

At this time, the left interval is orderly and the right interval is orderly to the right of the equation, so the DP is optimized by the monotone queue slope.

Divide and conquer right interval.

Merge sort by the right of the equation.

This code can refer to the example below bzoj1492: [NOI2007] Currency exchange cash.

In construction ...

y[j]=f[j]/(A[j]*rate[j]+b[j]) *rate[j]

x[j]=f[j]/(A[j]*rate[j]+b[j])

X[j]*a[i]+y[j]*b[i]<x[k]*a[i]+y[k]*b[i]

(X[j]-x[k]) *a[i]< (Y[k]-y[j]) *b[i]

(X[j]-x[k])/(Y[k]-y[j]) <b[i]/a[i]

#include <iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<algorithm>#include<cmath>using namespacestd;Const intmaxn=500010, inf=1e9;structpoiq{DoubleA, B, rate, K;intPOS;} Q[MAXN], NQ[MAXN];structpoip{Doublex, y;} P[MAXN], NP[MAXN];intN, Que[maxn], ST[MAXN];DoubleF[MAXN];BOOL operator< (Poiq A, Poiq b) {returnb.k-a.k>1e-9;} InlineDoublexlintAintb) {returnFabs (p[b].x-p[a].x) >1e-9? (P[A].Y-P[B].Y)/(p[b].x-p[a].x):-inf;}voidSolveintLintR) {    if(l==R) {F[l]=max (F[l], f[l-1]); p[l].x=f[l]/(q[l].a*q[l].rate+q[l].b); P[l].y=p[l].x*q[l].rate; return; }    intMid= (l+r) >>1, L1=l, l2=mid+1;  for(inti=l;i<=r;i++)    if(Q[i].pos<=mid) nq[l1++]=q[i];Elsenq[l2++]=Q[i];  for(inti=l;i<=r;i++) q[i]=nq[i]; Solve (l, mid); intL=1, r=0;  for(inti=l;i<=mid;i++)    {         while(L<r && XL (que[r-1], Que[r])-XL (Que[r], i) >1e-9) r--; que[++r]=i; }     for(intI=mid+1; i<=r;i++)     {         while(L<r && Q[I].K-XL (que[l], que[l+1]) >1e-9) l++; F[q[i].pos]=max (F[q[i].pos], q[i].a*p[que[l]].y+q[i].b*p[que[l]].x); } Solve (Mid+1, R); L1=l, l2=mid+1, l=l;  while(L1<=mid && l2<=R)if(p[l2].x-p[l1].x>1e-9) NP[L]=P[L1], l1++, l++;ElseNP[L]=P[L2], l2++, l++;  while(L1<=mid) np[l]=p[l1], l1++, l++;  while(l2<=r) Np[l]=p[l2], l2++, l++;  for(inti=l;i<=r;i++) p[i]=np[i];}intMain () {scanf ("%D%LF", &n, &f[0]);  for(intI=1; i<=n;i++) {scanf ("%LF%LF%LF", &AMP;Q[I].A, &q[i].b, &q[i].rate); Q[I].K=Q[I].B/Q[I].A; q[i].pos=i; } sort (Q+1, q+1+N); Solve1, N); printf ("%.3lf\n", F[n]); return 0;}
View Code

Preliminary study on "algorithm" CDQ Division and Treatment

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.