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); } }