Genius ACM HihoCoder - 1384 倍增/归并排序模板

倍增可行长度和直接二分都可以保证对于每个左端点至多log次找到最远右端点

但是倍增的过程中所需要计算的长度是从小逐渐变大的,而且可以利用前一步倍增的有序数组做一轮归并,

整体就比直接二分右端点所需要计算的长度快一个log

//#include<bits/stdc++.h>  
//#pragma comment(linker, "/STACK:1024000000,1024000000")   
#include<stdio.h>  
#include<algorithm>  
#include<queue>  
#include<string.h>  
#include<iostream>  
#include<math.h>                    
#include<set>  
#include<map>  
#include<vector>  
#include<iomanip> 
#include<bitset>
using namespace std;         //

#define ll long long  
#define pb push_back  
#define FOR(a) for(int i=1;i<=a;i++) 
#define sqr(a) (a)*(a)
#define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
ll qp(ll a,ll b,ll mod){
	ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
}
struct DOT{ll x;ll y;};
const int dx[4]={0,0,-1,1};
const int dy[4]={1,-1,0,0};
const int inf=0x3f3f3f3f;  
const ll mod=1e9+7;


/******************************************************/
namespace fastIO{  
    #define BUF_SIZE 100000  
    #define OUT_SIZE 100000  
    #define ll long long  
    //fread->read  
    bool IOerror=0;  
    inline char nc(){  
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;  
        if (p1==pend){  
            p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);  
        if (pend==p1){IOerror=1;return -1;}  
        //{printf("IO error!\n");system("pause");for (;;);exit(0);}  
    }  
    return *p1++;  
}  
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}  
inline void read(int &x){  
    bool sign=0; char ch=nc(); x=0;  
    for (;blank(ch);ch=nc());  
    if (IOerror)return;  
    if (ch=='-')sign=1,ch=nc();  
    for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';  
    if (sign)x=-x;  
}  
inline void read(ll &x){  
    bool sign=0; char ch=nc(); x=0;  
    for (;blank(ch);ch=nc());  
    if (IOerror)return;  
    if (ch=='-')sign=1,ch=nc();  
    for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';  
    if (sign)x=-x;  
}  
inline void read(double &x){  
    bool sign=0; char ch=nc(); x=0;  
    for (;blank(ch);ch=nc());  
    if (IOerror)return;  
    if (ch=='-')sign=1,ch=nc();  
    for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';  
    if (ch=='.'){  
        double tmp=1; ch=nc();  
        for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');  
    }  
    if (sign)x=-x;  
}  
inline void read(char *s){  
    char ch=nc();  
    for (;blank(ch);ch=nc());  
    if (IOerror)return;  
    for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;  
    *s=0;  
}  
inline void read(char &c){  
    for (c=nc();blank(c);c=nc());  
    if (IOerror){c=-1;return;}  
} 
#undef OUT_SIZE  
#undef BUF_SIZE  
}; using namespace fastIO;
/*****************************************************/

const int maxn=5e5+4;

int T;
int n,m;ll k;
int a[maxn];
int b[maxn];

int buf[maxn];

inline void merge(int l,int r,int m){
	int i=l,j=m+1;
	for(int k=l;k<=r;k++){
		if(j>r || i<=m &&b[i]<b[j])buf[k]=b[i++];
		else buf[k]=b[j++];
	}
}

int main(){
	read(T);
	while(T--){
		read(n);read(m);read(k);
		FOR(n)read(a[i]);

		int l=1,r=l;
	
		int ans=0;

		while(l<=n){

			ans++;
			int p=1;r=l;
			ll tmp;

			b[l]=a[l];

			while(p){
				if(r+p>n){p>>=1;continue;}
				tmp=0;
				for(int i=r+1;i<=r+p;i++){
					b[i]=a[i];
				}
				sort(b+r+1,b+1+r+p);
				merge(l,r+p,r);	//b[l,r] mer b[r+1,r+p]
	
				//for(int i=l;i<=p+r;i++){
				//	cout<<buf[i]<<" ";
				//}
				//cout<<endl;

				for(int i=l;i<=l+m-1;i++){
					if(i>r+p-i+l)break;
					tmp+=sqr(1ll*buf[i]-1ll*buf[r+p-i+l]);
				}
				//cout<<tmp<<endl;

				if(tmp<=k){	
					for(int i=l;i<=r+p;i++)b[i]=buf[i];
					r+=p;p<<=1;
				}else{
					p>>=1;
				}
			}
			l=r+1;
		}

		printf("%d\n",ans);
	}
}


posted @ 2018-02-06 00:21  Drenight  阅读(251)  评论(0编辑  收藏  举报