歸併排序和cdq分治

2021-09-26 19:38:54 字數 3687 閱讀 7454

#includeusing namespace std;

typedef long long ll;

const int n=5e5+9;

int a[n],temp[n],n;

ll ans=0;

void merge_sort(int l,int r)

while(p<=mid)temp[x++]=a[p++];

for(int i=l;i<=r;i++)a[i]=temp[i];

}int main()a[n];

int b[m],rk[n],v[n];

int n,k;

bool cmp1(t t1,t t2)

for(int i=l;i>n>>k;

for(int i=1;i<=n;++i)cin>>a[i].x>>a[i].y>>a[i].z;

sort(a+1,a+n+1,cmp1);

int nn=0,c=0;

for(int i=1;i<=n;i++)

cdq(1,nn);

for(int i=1;i<=nn;i++)v[a[i].ans+a[i].cnt-1]+=a[i].cnt;

for(int i=0;ipoints and rectangles(這裡不用注意下一題的排序,因為它的時間,第一維就是遞增的)

題意:

輸入q(1e5),接下來q行;

每行輸入 1,x,y                     表示在平面上加乙個點

或 2,x1,y1,x2,y2       表示在平面上加乙個矩形

問對於每乙個操作後,有多少個對點和矩形(點在矩形內)

題解:

經典偏序問題,按時間,橫座標,縱座標形成三維偏序。

分兩種情況:

1、矩形對答案的貢獻,設矩形為(t,x1,y1,x2,y2),即算在小於t時間的sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1],

2、點對答案的貢獻,設點為(x,y)與上面符號相反的求就好了。

#includeusing namespace std;

typedef long long ll;

const int n=1e6+9;

int q,na,x[n],y[n],nx,ny;

struct ta[n];

ll ans[n];

int f[n];

void add(int x,int y)

if(a[i].id==1)ans[a[i].t]+=query(a[i].y)*a[i].z;

}for(int i=l;i=mid+1;i--)

if(a[i].id==0)ans[a[i].t]+=query(n-2)-query(a[i].y-1);

}for(int i=mid;i>p;i--)if(a[i].id==1)add(a[i].y,-a[i].z);

}int main(),x[++nx]=x1,y[++ny]=y1;

if(opt==2);

a[++na]=(t);

a[++na]=(t);

a[++na]=(t);}}

sort(x+1,x+nx+1),sort(y+1,y+ny+1);

nx=unique(x+1,x+nx+1)-x-1,ny=unique(y+1,y+ny+1)-y-1;

for(int i=1;i<=na;i++)a[i].x=getidx(a[i].x),a[i].y=getidy(a[i].y);

cdq(1,na);

for(int i=1;i<=q;i++)ans[i]+=ans[i-1],printf("%lld\n",ans[i]);

return 0;

}

twinkle(排序一定要注意 插入優先於查詢,我因為這個調了乙個半小時)

題意:

輸入n(5e4),q(5e4),c(1e9);分別表示n顆星星,q個詢問,星星最大亮度為c(c+1變0)

接下來n行輸入x,y,s(s<=c),表示x,y處有一顆亮度為s的星星。

接下來輸入q行;

每行輸入t(t<=c),x1,y1,x2,y2;問過了t時間該矩形內星星的亮度和為多少。

題解:

由於s+t<=2*c,所以最多減一次c就可,先把矩形內星星亮度取和,加上t的貢獻,最後減去多少個超過c的貢獻。

現在要求該矩形內星星個數和星星亮度大於c-t的個數。

於是就變成了乙個求(橫座標,縱座標,星星亮度)的三維偏序問題;(注意星星盡量放前面)

#includeusing namespace std;

typedef long long ll;

const int n=1e6+9;

int n,q,c,na,nx;

int f[n],x[n],tim[n];

void add(int x,int y)

if(a[i].id)gs[a[i].id]+=js*a[i].z,ans[a[i].id]+=he*a[i].z,les[a[i].id]+=query(a[i].s)*a[i].z;

}for(int i=l;i>n>>q>>c;

for(int i=1,xx,y,s;i<=n;i++)cin>>xx>>y>>s,a[++na]=(t),x[++nx]=s;

for(int i=1,t,x1,y1,x2,y2;i<=q;i++);

a[++na]=(t);

a[++na]=(t);

a[++na]=(t);

x[++nx]=c-t;

}sort(x+1,x+nx+1);nx=unique(x+1,x+nx+1)-x-1;

for(int i=1;i<=na;i++)a[i].s=getidx(a[i].s);

sort(a+1,a+na+1,cmp1);

cdq(1,na);

for(int i=1;i<=q;i++)cout<四維偏序問題:

四維偏序裸題思路,cdq套cdq即a通過flag標記,在cdq2的時候,b已經是有序的了,所以只用再c歸併,d樹狀陣列求和。

#include #include #include #include using namespace std;

typedef long long ll;

const int n=5e4+5;

inline int read()

while(c>='0'&&c<='9')

return x*f;

}int n;

struct operationa[n],t1[n],t2[n];

int c[n];

inline int lowbit(int x)

inline void add(int p,int v)

inline int sum(int p)

int ans;

void cdq2(int l,int r)

for(int i=l;i<=r;i++) a[i]=t[i];

cdq2(l,r);

}int main()

歸併排序(分治)

把乙個陣列 a 分成兩個部分 s,m m 1,e 假設兩部分分別有序,把這兩部分合併到另一陣列中 tmp 保證該陣列有序,然後再把資料 e s 1拷貝回陣列a 分治的原理。把資料無限二分,最後比較兩個數即可。遞迴實現。includeusing namespace std int a 10 int b...

歸併排序 分治

歸併 將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有 序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為二路歸併。歸併的本質 空間換時間,通過申請乙個額外陣列儲存中間變化,從而實現排序 歸併排序核心步驟 歸併排序的特性總結 歸併的缺點在於需要o n 的空間複雜度,歸併排序的思...

分治 歸併排序

將兩個排序好的陣列歸併過程如下 紅色的 1 是左邊起始位置 綠色的 2 是右邊起始位置 灰色的 最右邊 是右邊終點位置 include using namespace std typedef int elementtype l 左邊起始位置,r 右邊起始位置,rightend 右邊終點位置 void...