<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      「USACO24DEC G」Cowdepenence 題解

      「USACO24DEC G」Cowdepenence 題解


      知識點

      根號分治。

      分析

      \(O(n\sqrt{n}\log_2{n})\)

      我們考慮先將每種顏色分開,然后對于每種顏色分別處理。

      可以類比數論分塊,我們會發現當距離范圍 \(x\) 處于某個區間 \([l,r]\) 時,友誼小組的最小數量 \(cnt\) 的值是相同的,而且根據數論分塊的結論,本質不同的 \(cnt\) 數量不會超過 \(\sqrt{n}\)

      顯然 \(x,cnt\) 的關系滿足單調性,所以我們可以直接暴力二分 \(x\) 的闕值,進行檢驗,并且對每次重復檢驗的 \(x\) 進行記憶化,然后差分統計答案。

      unordered_map<int,int> rec;
      
      void Solve(const Vi &vec) {
      	for(int L(1),R(1),c(Check(vec,1)); L<=n; c=Check(vec,L=++R)) {
      		for(int l(L+1),r(n),mid((l+r)>>1); l<=r; mid=(l+r)>>1)
      			Check(vec,mid)>=c?R=mid,l=mid+1:r=mid-1;
      		ans[L]+=c,ans[R+1]-=c;
      	}
      	rec.clear();
      }
      

      假設我們現在處理的顏色有 \(k\) 個,那么我們有兩種檢驗方法:

      • \(O(k)\)

        直接一遍掃過去。

        int Check1(const Vi &vec,const int &lim) {
        	int cnt(0),sta(0);
        	for(const int &x:vec)if(!sta||x-sta>lim)++cnt,sta=x;
        	return cnt;
        }
        
      • \(O(\frac{n}{x}\log_2{k})\)

        我們中間不斷二分下一個點。

        int Check2(const Vi &vec,const int &lim) {
        	int cnt(0),sta(vec.front());
        	while(true) {
        		++cnt;
        		int it(upper_bound(vec.begin(),vec.end(),sta+lim)-vec.begin());
        		if(it==(int)vec.size())break;
        		sta=vec[it];
        	}
        	return cnt;
        }
        

      我們每次取其中復雜度小的一個。

      int Check(const Vi &vec,const int &lim) {
      	if(rec.count(lim))return rec[lim];
      	auto cal=[&]() -> ll { return (ll)rec.size()*lim/n; };
      	return rec[lim]=(cal()<20&&(1<<cal())<(int)rec.size()?Check1(vec,lim):Check2(vec,lim));
      }
      

      時間復雜度 \(O(n\sqrt{n}\log_2{n})\)。

      int n;
      int a[N],b[N],ans[N];
      Vi vec[N];
      
      int Check1(const Vi &vec,const int &lim) {
      	int cnt(0),sta(0);
      	for(const int &x:vec)if(!sta||x-sta>lim)++cnt,sta=x;
      	return cnt;
      }
      
      int Check2(const Vi &vec,const int &lim) {
      	int cnt(0),sta(vec.front());
      	while(true) {
      		++cnt;
      		int it(upper_bound(vec.begin(),vec.end(),sta+lim)-vec.begin());
      		if(it==(int)vec.size())break;
      		sta=vec[it];
      	}
      	return cnt;
      }
      
      unordered_map<int,int> rec;
      
      int Check(const Vi &vec,const int &lim) {
      	if(rec.count(lim))return rec[lim];
      	auto cal=[&]() -> ll { return (ll)vec.size()*lim/n; };
      	return rec[lim]=(cal()<20&&(1<<cal())<(int)vec.size()?Check1(vec,lim):Check2(vec,lim));
      }
      
      void Solve_Min(const Vi &vec) {
      	for(int L(1),R(1),c(Check(vec,1)); L<=n; c=Check(vec,L=++R)) {
      		for(int l(L+1),r(n),mid((l+r)>>1); l<=r; mid=(l+r)>>1)
      			Check(vec,mid)>=c?R=mid,l=mid+1:r=mid-1;
      		ans[L]+=c,ans[R+1]-=c;
      	}
      	rec.clear();
      }
      
      signed main() {
      #ifdef Plus_Cat
      	freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
      #endif
      	I(n);
      	FOR(i,1,n)I(a[i]),b[i]=a[i];
      	sort(b+1,b+n+1),b[0]=unique(b+1,b+n+1)-b-1;
      	FOR(i,1,n)a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;
      	FOR(i,1,n)vec[a[i]].push_back(i);
      	FOR(i,1,b[0])Solve_Min(vec[i]);
      	FOR(i,1,n)O(ans[i]+=ans[i-1],'\n');
      	return 0;
      }
      

      \(O(n\sqrt{n\log_2{n}})\)

      發現其實相同顏色中 \(x\le \sqrt{n}\) 的部分,直接暴力求解反而更快,這部分復雜度變成了 \(O(n\sqrt{n})\)

      進一步調整塊長,發現如果 \(x\le \sqrt{n\log_2{n}}\) 的部分都暴力求解,復雜度就變成了 \(O(n\sqrt{n\log_2{n}})\)。

      void Solve(const Vi &vec) {
      	FOR(i,1,Bl) {
      		int tmp(Check1(vec,i));
      		ans[i]+=tmp,ans[i+1]-=tmp;
      	}
      	for(int L(Bl+1),R(Bl+1),c(Check(vec,Bl+1)); L<=n; c=Check(vec,L=++R)) {
      		for(int l(L+1),r(n),mid((l+r)>>1); l<=r; mid=(l+r)>>1)
      			Check(vec,mid)>=c?R=mid,l=mid+1:r=mid-1;
      		ans[L]+=c,ans[R+1]-=c;
      	}
      	rec.clear();
      }
      
      signed main() {
      #ifdef Plus_Cat
      	freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
      #endif
      	I(n),Bl=ceil(sqrt(n*log2(n)));
      	FOR(i,1,n)I(a[i]),b[i]=a[i];
      	sort(b+1,b+n+1),b[0]=unique(b+1,b+n+1)-b-1;
      	FOR(i,1,n)a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;
      	FOR(i,1,n)vec[a[i]].push_back(i);
      	FOR(i,1,b[0])Solve(vec[i]);
      	FOR(i,1,n)O(ans[i]+=ans[i-1],'\n');
      	return 0;
      }
      

      \(O(n\sqrt{n})\)

      要求一個整數序列 \((a_1,a_2,\ldots,a_n)\)。已知:

      • 它是非遞增的,即 \(a_k \ge a_{k+1}\)
      • \(0 \le a_k \le \frac{n}{k}\)。

      可以在 \(O(C)\) 時間內得到 \(a_k\) 的一個值,則可以在 \(O(n+\sqrt{n}C)\) 的復雜度內求出整個序列。

      ——Determine A Non-Increasing Integer Sequence of Length n with a[k]<=n/k in O(sqrt(n)) Steps - Codeforces

      我們仿照上面那篇博文分析一下復雜度:

      \(a_0=n+1,a_{n+1}=0\),然后開始分治:

      假設現在分治區間為 \([l,r]\),則:

      • 如果 \(a_{l-1}=a_{r+1}\),則全部賦為同值。
      • 否則求出 \(a_{mid}\),然后遞歸 \([l,mid),(mid,r]\)

      那么對于深度為 \(d\) 的一層,求值操作數量是 \(O(2^{\fracw0obha2h00{2}})\) 級別的。

      所以總復雜度為:

      \[\sum_{d=0}^{\lceil \log_2{n} \rceil} 2^{\fracw0obha2h00{2}} \\ \]

      \(O(\sqrt{n})\)。那么我們也這么干就可以了。

      //#define Plus_Cat ""
      #include<bits/stdc++.h>
      #define INF 0x3f3f3f3f
      #define ll long long
      #define Vi vector<int>
      #define RCL(a,b,c,d) memset(a,b,sizeof(c)*(d))
      #define FOR(i,a,b) for(int i(a);i<=(int)(b);++i)
      #define DOR(i,a,b) for(int i(a);i>=(int)(b);--i)
      #define tomax(a,...) ((a)=max({(a),__VA_ARGS__}))
      #define tomin(a,...) ((a)=min({(a),__VA_ARGS__}))
      #define EDGE(g,i,x,y) for(int i=(g).h[(x)],y=(g)[(i)].v;~i;y=(g)[(i=(g)[i].nxt)>0?i:0].v)
      #define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);return Main();}signed Main
      using namespace std;
      constexpr int N(1e5+10);
      
      namespace IOEcat {
      	//...
      } using namespace IOEcat;
      
      int n,Bl;
      int a[N],b[N],ans[N];
      Vi vec[N];
      
      int Check1(const Vi &vec,const int &lim) {
      	int cnt(0),sta(0);
      	for(const int &x:vec)if(!sta||x-sta>lim)++cnt,sta=x;
      	return cnt;
      }
      
      int Check2(const Vi &vec,const int &lim) {
      	int cnt(0),sta(vec.front());
      	while(true) {
      		++cnt;
      		int it(upper_bound(vec.begin(),vec.end(),sta+lim)-vec.begin());
      		if(it==(int)vec.size())break;
      		sta=vec[it];
      	}
      	return cnt;
      }
      
      
      int Check(const Vi &vec,const int &lim) {
      	auto cal=[&]() -> ll { return (ll)vec.size()*lim/n; };
      	return cal()<20&&(1<<cal())<(int)vec.size()?Check1(vec,lim):Check2(vec,lim);
      }
      
      void Sep(int l,int r,int vl,int vr,const Vi &vec) {
      #define mid ((l+r)>>1)
      	if(l>r)return;
      	if(vl==vr)return ans[l]+=vl,ans[r+1]-=vr,void();
      	int vm(Check(vec,mid));
      	ans[mid]+=vm,ans[mid+1]-=vm,Sep(l,mid-1,vl,vm,vec),Sep(mid+1,r,vm,vr,vec);
      #undef mid
      }
      
      signed main() {
      #ifdef Plus_Cat
      	freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
      #endif
      	I(n),Bl=ceil(sqrt(n*log2(n)));
      	FOR(i,1,n)I(a[i]),b[i]=a[i];
      	sort(b+1,b+n+1),b[0]=unique(b+1,b+n+1)-b-1;
      	FOR(i,1,n)a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;
      	FOR(i,1,n)vec[a[i]].push_back(i);
      	FOR(i,1,b[0])Sep(1,n,n,1,vec[i]);
      	FOR(i,1,n)O(ans[i]+=ans[i-1],'\n');
      	return 0;
      }
      
      posted @ 2025-05-07 21:58  Add_Catalyst  閱讀(9)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 中文字幕日韩精品亚洲一区 | 国产96在线 | 亚洲| 成人亚洲一级午夜激情网| 亚洲中文字幕第一页在线| 天堂av最新版中文在线| 国产午夜精品理论大片| 国产重口老太和小伙| 免费极品av一视觉盛宴| 一二三四中文字幕日韩乱码| 国产一区二区三区免费观看| 女人高潮流白浆视频| 久久精品国产成人午夜福利| 无码国模国产在线观看免费| 亚洲一线二线三线品牌精华液久久久 | 国产精品尤物午夜福利| 狠狠干| 午夜夫妻试看120国产| 日韩国产成人精品视频| 美女胸18下看禁止免费视频| 欧美成人无码a区视频在线观看| 日本无遮挡吸乳视频| 亚洲AV日韩AV综合在线观看| 忘忧草www日本韩国| 2021国产精品视频网站| 蜜臀av日韩精品一区二区| 黑人大群体交免费视频| 简阳市| 亚洲日韩性欧美中文字幕| 欧美亚洲另类自拍偷在线拍| 在线播放国产精品亚洲| 欧美老熟妇乱子伦牲交视频| 亚洲综合在线日韩av| 无码国产精品成人| 人妻少妇精品无码专区二区| 欧美成人午夜精品免费福利| 九九热在线视频免费观看| 中文字幕无码视频手机免费看| 亚洲国产精品一区在线看| 国产精品爱久久久久久久| 国精品午夜福利视频不卡| 少妇和邻居做不戴套视频|