cdq partition study notes (the non-teaching)

cdq partition study notes (the non-teaching)

(Non-full version, to be more)

  1. What cdq partition that?

cdq partition is a big problem into two between the scale is the answer to half of its sub-problems, and two sub-problems of statistical algorithms, complexity $ nklogn $

  1. cdq partition of how to write?

See examples of code

  1. cdq partition can do?

In my current understanding, cdq partition is used to solve some partial orders and related topics, such as a point on the answer only from a small number of property than it is to the point of transfer, then you can use cdq partition to update the answer

Recommended topics:

t1.

[Template] three-dimensional partial order (Mo flowers)

cdq partition template title, pre-cheese: cdq divide and conquer, Fenwick tree

//I love Nanami Chiaki
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
const int maxn=1e5+7;
int n,k;
int ans[maxn],res[maxn];
int dat[maxn<<1];
bool hve[maxn];
struct Flower{
    int a,b,c,id;
}f[maxn],t[maxn];
inline bool cmp1(Flower X,Flower Y){
    return (X.a^Y.a)?(X.a<Y.a):((X.b^Y.b)?(X.b<Y.b):(X.c<Y.c));
}
inline void add(int p,int v){
    while (p<=k){
        dat[p]+=v;
        p+=lowbit(p);
    }
}
inline int sum(int p){
    int re=0;
    while (p){
        re+=dat[p];
        p-=lowbit(p);
    }
    return re;
}
void cdq1(int l,int r){
    if (l==r) return;
    int mid=(l+r)>>1;
    cdq1(l,mid);
    cdq1(mid+1,r);
    int i=l,j=mid+1,sz=l;
    while (i<=mid || j<=r){
        if (i>mid){
            t[sz++]=f[j];
            ans[f[j].id]+=sum(f[j].c);
            j++;            
        }
        else if (j>r || f[i].b<=f[j].b){
            t[sz++]=f[i];
            hve[f[i].id]=true;
            add(f[i++].c,1);
        }
        else{
            t[sz++]=f[j];
            ans[f[j].id]+=sum(f[j].c);
            j++;
        }
    }
    for (int i=l;i<=r;i++){
        f[i]=t[i];
        if (hve[f[i].id]){
            hve[f[i].id]=false;
            add(f[i].c,-1);
        }
    }
}
int main(){
    scanf("%d%d",&n,&k);
    for (int i=0;i<n;i++){scanf("%d%d%d",&f[i].a,&f[i].b,&f[i].c);f[i].id=i;}
    sort(f,f+n,cmp1);
    int prea=-1,preb=-1,prec=-1,num=0;
    for (int i=n;i>=0;i--){
        if (f[i].a==prea && f[i].b==preb && f[i].c==prec) ans[f[i].id]=num++;
        else{
            prea=f[i].a;preb=f[i].b;prec=f[i].c;num=1;
        }
    }
    cdq1(0,n-1);
    for (int i=0;i<n;i++) res[ans[i]]++;
    for (int i=0;i<n;i++) printf("%d\n",res[i]);
    return 0;
}

Puzzled look when say something about their own solution to a problem / write program

  1. Why do you write is right?

    • After that is the most intuitive I doubt, thought for a while, I got the answer.

    • In the main function, we have to ensure that a property ordered (look carefully in the sort function cmp will find b and c have to be sequenced), which ensures that the number of the answer must be made to update the number in front of the back ( the number can not go back to update the previous number? there is a special case, wait a minute to say), this is probably the basis cdq divide and conquer.

    • Then cdq1 function, we first divide and conquer,Seems to have heard the question, regardless of prior treatment, but I feel like I have not met, after all, I only worked 2 title, Careful observation while loop discovered that returns an array of f turned out to be based on the result of the sort attribute b, this being there is a very wonderful place.

    • Such a child will not be out of order it? Will be out of order, but no relationship between the two sub answer is updated between the internal process has been finished, and the remaining is updated between the child answers the question, because we start a row over the order, so the front of the must meet a number of attributes than or equal to the back of the small number, which means that even if the two sub-problems of a both out of order, but a child behind a certain issue than a child in front of a small problem or equal.

    • This time two sub-questions b orderly merger, first add a small b in the process of merging the new sequence go, and maintenance with a tree in front of an array of sub-problems c = k is the number of simultaneously for each point of a problem child behind, his answer would add the number of dendritic array c is smaller than its number on it (this is because the number of the tree in the array must be smaller than that of b (because it added more than earlier), and a smaller than it is, as I said before the reason).

To save time you tune title, I also wrote a error-prone point of solving the problem

  1. When ai = aj, bi = bj, ci = cj time, even if i came in front of j, j i can be updated, then we need to deal with it this particular case on the line, see the code

t2

Angel Doll

This question is not why the data to write up an enhanced version of the name is too weak because I could not pass that question

Front cheese: cdq divide and conquer, Fenwick tree

Version 1: TLE version (cdq sets cdq)

//I love Nanami Chiaki
#include<bits/stdc++.h>
using namespace std;
const int maxn=500007;
const int maxp=1000007;
const int inf=1e9+7;
inline int read(){
    int re=0;char c=getchar();
    while (c<'0' || c>'9') c=getchar();
    while (c>='0' && c<='9'){re=(re<<1)+(re<<3)+(c^48);c=getchar();}
    return re;
}
struct Node{int x,y,t,op,f1;}hve[maxn<<1],hve1[maxn<<1],hve2[maxn<<1];
int n,m,mm=0,ans[maxn];
inline bool cmp(Node X,Node Y){return (X.x^Y.x)?(X.x<Y.x):((X.y^Y.y)?(X.y<Y.y):(X.t<Y.t));}
void solveit2(int l,int r){
    if (l==r) return;
    int mid=(l+r)>>1;
    solveit2(l,mid);
    solveit2(mid+1,r);
    int i=l,j=mid+1,sz=l,mx=-inf;
    while (i<=mid || j<=r){
        if (i>mid){
            if (hve1[j].op && hve1[j].f1) ans[hve1[j].op]=min(hve1[j].x+hve1[j].y-mx,ans[hve1[j].op]);
            hve2[sz++]=hve1[j++];
        }
        else if (j>r || hve1[i].t<hve1[j].t){
            if (!hve1[i].op && !hve1[i].f1) mx=max(mx,hve1[i].x+hve1[i].y);
            hve2[sz++]=hve1[i++];           
        }
        else{
            if (hve1[j].op && hve1[j].f1) ans[hve1[j].op]=min(hve1[j].x+hve1[j].y-mx,ans[hve1[j].op]);
            hve2[sz++]=hve1[j++];
        }
    }
    for (int i=l;i<=r;++i) hve1[i]=hve2[i];
}
void solveit1(int l,int r){
    if (l==r) return;
    int mid=(l+r)>>1;
    solveit1(l,mid);
    solveit1(mid+1,r);
    int i=l,j=mid+1,sz=i;
    while (i<=mid || j<=r){
        if (i>mid){hve1[sz++]=hve[j++];hve1[sz-1].f1=1;}
        else if (j>r || (hve[i].y<hve[j].y || (hve[i].y==hve[j].y && hve[i].t<hve[j].t))){hve1[sz++]=hve[i++];hve1[sz-1].f1=0;}
        else{hve1[sz++]=hve[j++];hve1[sz-1].f1=1;}
    }
    for (int i=l;i<=r;++i) hve[i]=hve1[i];
    solveit2(l,r);
}
int main(){
    n=read();m=read();
    for (int i=0;i<n;++i){int x=read(),y=read();hve[i].x=x;hve[i].y=y;hve[i].t=0;hve[i].op=0;}
    for (int j=0;j<m;++j){
        int T=read(),x=read(),y=read();hve[n+j].x=x;hve[n+j].y=y;hve[n+j].t=j+1;
        if (T==1) hve[n+j].op=0;
        else{hve[n+j].op=++mm;ans[mm]=inf;}
    }
    n+=m;m=mm;
    for (int k=0;k<4;++k){
        sort(hve,hve+n,cmp);
        solveit1(0,n-1);
        for (int j=0;j<n;++j){swap(hve[j].x,hve[j].y);hve[j].x=maxp-6-hve[j].x;}
    }
    for (int i=1;i<=m;++i) printf("%d\n",ans[i]);
    return 0;
}

Version 2: AC version (cdq sets Fenwick tree) (also in the plus something, is to begin with a series of header files #pragma GCC can optimize over manual embarrassing) (Why not put up ugly (?)? up!)

To see my records submitted to AC (alternating reason is not large because too many large submission is limited, and once again embarrassed manual)

//I love Nanami Chiaki
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
const int maxn=300007;
const int maxp=1000007;
const int inf=1e9+7;
inline int read(){
    int re=0;char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)){re=(re<<1)+(re<<3)+(c^48);c=getchar();}
    return re;
}
struct Node{int x,y,t,op;bool ff;}hve[maxn<<1],hve1[maxn<<1];
int n,m,mm=0,ans[maxn],dat[maxn];
inline bool cmp(Node X,Node Y){return (X.x^Y.x)?(X.x<Y.x):((X.y^Y.y)?(X.y<Y.y):(X.t<Y.t));}
inline void mymax(int &x,int y){if (x<y) x=y;}
inline void mymin(int &x,int y){if (x>y) x=y;}
inline void myswap(int &x,int &y){int t=x;x=y;y=t;}
inline void add(int p,int v){while (p<=m && dat[p]<v){mymax(dat[p],v);p+=lowbit(p);}}
inline int query(int p){int re=0;while (p){mymax(re,dat[p]);p-=lowbit(p);}return (re==0)?-inf:re;}
inline void clear(int p){while (p<=m && dat[p]){dat[p]=0;p+=lowbit(p);}} 
void solveit1(int l,int r){
    if (l==r) return;
    int mid=(l+r)>>1;
    solveit1(l,mid);
    solveit1(mid+1,r);
    int i=l,j=mid+1,sz=i;
    while (i<=mid || j<=r){
        if (i>mid){if (hve[j].op) mymin(ans[hve[j].op],hve[j].x+hve[j].y-query(hve[j].t));hve1[sz++]=hve[j++];}
        else if (j>r || (hve[i].y<hve[j].y || (hve[i].y==hve[j].y && hve[i].t<hve[j].t))){if (!hve[i].op) add(hve[i].t+1,hve[i].x+hve[i].y);hve1[sz++]=hve[i++];hve1[sz-1].ff=true;}
        else{if (hve[j].op) mymin(ans[hve[j].op],hve[j].x+hve[j].y-query(hve[j].t));hve1[sz++]=hve[j++];}
    }
    for (int i=l;i<=r;++i){
        if (hve1[i].ff){clear(hve1[i].t+1);hve1[i].ff=false;}
        hve[i]=hve1[i];
        ++i;if (i>r) break;
        if (hve1[i].ff){clear(hve1[i].t+1);hve1[i].ff=false;}
        hve[i]=hve1[i];
    }
}
int main(){
    n=read();m=read();
    int x,y,T;
    for (int i=0;i<n;++i){x=read();y=read();hve[i].x=x;hve[i].y=y;hve[i].t=0;hve[i].op=0;}
    for (int j=0;j<m;++j){
        T=read();x=read();y=read();hve[n+j].x=x;hve[n+j].y=y;hve[n+j].t=j+1;
        if (T==1) hve[n+j].op=0;
        else{hve[n+j].op=++mm;ans[mm]=inf;}
    }
    n+=m;
    for (int k=0;k<4;++k){
        sort(hve,hve+n,cmp);
        solveit1(0,n-1);
        for (int j=0;j<n;++j){
            myswap(hve[j].x,hve[j].y);hve[j].x=maxp-6-hve[j].x;
            ++j;if (j>=n) break;
            myswap(hve[j].x,hve[j].y);hve[j].x=maxp-6-hve[j].x;
        }
    }
    for (int i=1;i<=mm;++i) printf("%d\n",ans[i]);
    return 0;
}

This question is probably thinking:

Of course, I also see the solution to a problem, at the beginning did not feel completely turned cdq the problem, though, is in question cdq table inside looking for.

This question is the idea that you can use for each point and point queries are located a time stamp, and then for each query point, in fact, we calculate it is to the lower left corner in front of it and timestamp x + points the maximum value of y on it, the answer is min (xi + xj-mx), this of course is wrong, as well as the upper left, upper right, lower right, etc. several directions, but the position is essentially similar to the lower left corner and go beg on the line (in fact, turn out the map click on it), then the problem is transformed to ask four times for each query point i only x <= xi, y <= yi, t point <ti's only the problem can be updated, a look that is not the problem it

version 1:

I wanted to use this question to learn about cdq sets cdq, after all, the previous solution can not solve that problem of four-dimensional partial order, the result of the successful use of this method on the wrong problem

But still talk about it

  1. cdq is set like this cdq
    • The first step was in accordance with a sorting
    • And then into the first partition or in solve1, and then sorted according to b to deal with, but this time we do not consider maintenance with other data structures. Then we can put forward a number of sub-issues play a subscript 0, after a number of sub-issues play a subscript 1, the subscript represents the number 0 can be used to update the index number of the answer to 1 ( in the sense of a property)
    • Then we have to sort according to attribute b Well, then we enter solve2
    • In solve2, we still have to deal with the problem of partition, we know that this partition is used to handle the answer between the two sub-problems solve1 in, so we only use index number of 0 to update subscript number 1, the partition process, solve2 while loop process is marked before solve2 a sub-problem at a number from 0 to a child under question after solve2 marked as number 1 answer is updated (because the two sub-solve2 divide and conquer question, the answer updating such within them have finished processing), then in accordance with c merge sort, since the array solve2 beginning accordance b ordered, the number of attributes b before a sub-problems must be smaller than a rear sub-problem attribute b in a case, the merge process c, the number can be updated before a number mx, c attribute must be smaller than it. And then labeled with the number 0 (the previous sub-problem) to update mx, mx updated index number 1 (after a sub-problem), no problem
  2. About four-dimensional partial process sequence probably is the same, that is, into a first ordered, and then put into a case where the 0/1 b orderly arranged, and then into the b 0/1 under the circumstances, the c arranged in an orderly, last updated answer on it

Version 2:

Card often card dead ah! ! ! , Uncomfortable

I use / learn a few card tricks often

  1. Loop unrolling, new school, I feel quite good, not their own Baidu, I also Baidu's

  2. Custom max, min, swap

  3. Simple and fast reading

  4. Duitou file that is in front (to help me optimize half the time, manual embarrassing)

To be more

Guess you like

Origin www.cnblogs.com/xxjAc/p/12109935.html