日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces:372(div1)div373(div2)

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces:372(div1)div373(div2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • CF373A Collecting Beats is Fun
    • Description\text{Description}Description
    • Solution\text{Solution}Solution
    • Code\text{Code}Code
  • CF373B Making Sequences is Fun
    • Description\text{Description}Description
    • Solution\text{Solution}Solution
  • CF372A Counting Kangaroos is Fun
    • Description\text{Description}Description
    • Solution\text{Solution}Solution
    • Code\text{Code}Code
  • CF372B Counting Rectangles is Fun
    • Description\text{Description}Description
    • Solution\text{Solution}Solution
    • Code\text{Code}Code
  • CF372D Choosing Subtree is Fun
    • Description\text{Description}Description
    • Solution\text{Solution}Solution

前言

中規中矩的比賽 想不出形容詞了
373AB是水題
372ABD都是小清新且碼量較小的好題
372C之前做過了
372E毒瘤幾何+組合數學,沒有洛谷題解,CF題解完全看不懂,直接棄療qwq

CF373A Collecting Beats is Fun

Description\text{Description}Description

一共有 4×4=164\times4=164×4=16 個格子,每個格子 (i,j)(i,j)(i,j) 需要在 ti,jt_{i,j}ti,j? 時刻點擊(若為星號則不需要點擊),你每只手同一時刻只能點擊 kkk 個格子(注意你有兩只手!),求你是否能完成任務。
ti,jt_{i,j}ti,j? 是一個 1?91-91?9 的數字。

Solution\text{Solution}Solution

水題。
4×44\times44×4 掃一遍,開一個桶記錄每個時刻需要點多少個格子,最后判是否有桶超過 2k2k2k 即可。

Code\text{Code}Code

#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=2e6+100; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m; int bac[12]; signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();for(int i=1;i<=4;i++){for(int j=1;j<=4;j++){char c;scanf(" %c",&c);if(c!='.') bac[c-'0']++;//debug("%d\n",c-'0');}}for(int i=1;i<=9;i++){if(bac[i]>2*n){printf("NO\n");return 0;}}printf("YES\n");return 0; } /**/

CF373B Making Sequences is Fun

Description\text{Description}Description

定義 S(i)=iS(i)=iS(i)=i 的位數,如 S(893)=3,S(114514)=6S(893)=3,S(114514)=6S(893)=3,S(114514)=6

xxx 的費用為 k×S(i)k\times S(i)k×S(i)

你有 www 元錢,要從 mmm 開始連續添加盡量多的數 (m,m+1,m+2,?)(m,m+1,m+2,\cdots)(m,m+1,m+2,?) 組成一個序列,問這個序列最長有多長。
w,m≤1016,k≤109w,m\le 10^{16},k\le10^9w,m1016,k109

Solution\text{Solution}Solution

小清新模擬。
可以先令 w←?wk?w\gets \lfloor \dfrac{w}{k}\rfloorw?kw??kkk 的影響去掉。
一直往進位處跳直到不能繼續跳位置,然后把剩下的個數求出來,過程中貢獻加起來即可。

#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=2e6+100; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n; ll w,m,k; inline ll calc(ll x){int res(0);while(x) x/=10,++res;return res; } ll mi[20]; signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifmi[1]=1;for(int i=2;i<=18;i++) mi[i]=mi[i-1]*10;w=read();m=read();k=read();w/=k;ll o=calc(m),ans(0);while((mi[o+1]-m)*o<=w){ans+=mi[o+1]-m;w-=(mi[o+1]-m)*o;++o;m=mi[o];//printf("o=%lld w=%lld ans=%lld m=%lld\n",o,w,ans,m);} ans+=w/o;printf("%lld\n",ans);return 0; } /* */

CF372A Counting Kangaroos is Fun

Description\text{Description}Description

nnn 只袋鼠,每只的大小為 sis_isi?,每只大小為 xxx 的袋鼠可以裝在大小不少于 2x2x2x 的袋鼠的袋子里。
每只袋鼠的袋子最多裝一只袋鼠,且裝在別的袋鼠袋子里的袋鼠不能繼續裝袋鼠(不能套娃),求最多能讓多少只袋鼠被裝入別的袋鼠的袋子。

Solution\text{Solution}Solution

一道本人做的不太好的題。
一開始顯然是想貪心,比如從大往小選,每個盡可能裝大的之類,但是都可以被輕易的 hack。
然后就寫了個垃圾的二分多只 log 艸過去了

下面講線性的貪心正解。
其實剛才樸素的貪心是可以借鑒的,唯一的錯誤就在與盡可能裝的的那只“大袋鼠”可能用來裝別的袋鼠。

證明:
由于裝的個數最多肯定不超過 n/2n/2n/2 個,所以最小的 n/2n/2n/2 只袋鼠肯定不會裝別人。
同時,如果某只袋鼠裝了一只不在這 n/2n/2n/2 只袋鼠里的袋鼠,那它改成這 n/2n/2n/2 只袋鼠中沒有被裝的一只(必然存在)也是不劣的。
所以這個貪心是真的。

維護雙指針從 n/2n/2n/2 開始盡可能的裝大的即可。

Code\text{Code}Code

(雙指針的代碼題解區很多了,這里就貼的一開始二分的碼,也算是另一種思路)

#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=2e6+100; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n; int a[N]; bool check(int k){int l=1,r=k+1;while(l<=k){while(r<n&&a[r]<2*a[l]) ++r;if(a[r]<2*a[l]) return false;++l;++r;}return true; } signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();for(int i=1;i<=n;i++) a[i]=read();sort(a+1,a+1+n);int st=0,ed=n/2;while(st<ed){int mid=(st+ed+1)>>1;if(check(mid)) st=mid;else ed=mid-1;}printf("%d\n",n-st);return 0; } /* */

CF372B Counting Rectangles is Fun

Description\text{Description}Description

給定一個 n?m{n * m}n?m0/10/10/1 矩陣, qqq 次詢問, 每次詢問指定一個子矩形, 求該子矩形種有多少個只包含 000 的子矩陣。
n,m≤40,q≤3×105n,m\le40,q\le3\times 10^5n,m40,q3×105

Solution\text{Solution}Solution

小清新水紫。
似乎已經把 O(nmq)O(nmq)O(nmq) 的復雜度寫在數據范圍上了…
考慮枚舉這個矩形的長和寬,那么剩下的就只能 O(1)O(1)O(1) 查詢。
不難想到前綴和
定義一個矩陣的坐標為右下點的坐標
按照這個坐標的定義對于每個長和寬 (a,b)(a,b)(a,b) 都 預處理出矩形個數的前綴和,復雜度 O(n2m2)O(n^2m^2)O(n2m2)
那么我們如果在 (x1,y1,x2,y2)(x1,y1,x2,y2)(x1,y1,x2,y2) 的矩形中詢問大小為 a×ba\times ba×b 的矩形,就相當于查詢坐標在 (x1+a?1,y1+b?1,x2,y2)(x1+a-1,y1+b-1,x2,y2)(x1+a?1,y1+b?1,x2,y2) 這個矩形內的 a×ba\times ba×b 的矩形的總個數。
總時間復雜度 O(n2m2+qnm)O(n^2m^2+qnm)O(n2m2+qnm)

PS:本題由于那個四維前綴和數組跨度太大,請務必**把記錄長寬的兩維開在后面!**這樣在回答詢問的時候始終是連續訪問,否則會由于過多的 cache miss 而超時…(至少對于我的垃圾碼是這樣)改完后跑的飛快毫無壓力。

后來看題解似乎有 O(n2m2)?O(1)O(n^2m^2)-O(1)O(n2m2)?O(1) 的神奇偏序前綴和魔法操作,也很妙。

Code\text{Code}Code

#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=2e6+100; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m,q; int sum[50][50],num[50][50][50][50]; inline int Sum(int x1,int y1,int x2,int y2){return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]; } /*inline int Num(int a,int b,int x1,int y1,int x2,int y2){return num[a][b][x2][y2]-num[a][b][x1-1][y2]-num[a][b][x2][y1-1]+num[a][b][x1-1][y1-1]; }*/ #define Num(a,b,x1,y1,x2,y2) num[x2][y2][a][b]-num[x1-1][y2][a][b]-num[x2][y1-1][a][b]+num[x1-1][y1-1][a][b] signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();m=read();q=read();for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) scanf("%1d",&sum[i][j]);}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];}for(int a=1;a<=n;a++){for(int b=1;b<=m;b++){for(int i=a;i<=n;i++){for(int j=b;j<=m;j++)num[i][j][a][b]=num[i-1][j][a][b]+num[i][j-1][a][b]-num[i-1][j-1][a][b]+(Sum(i-a+1,j-b+1,i,j)==0);}}}//debugfor(int i=1;i<=q;i++){int x1=read(),y1=read(),x2=read(),y2=read();int ans(0);for(int a=1;a<=x2-x1+1;a++){for(int b=1;b<=y2-y1+1;b++){ans+=Num(a,b,x1+a-1,y1+b-1,x2,y2);}}printf("%d\n",ans);}return 0; } /* */

CF372D Choosing Subtree is Fun

Description\text{Description}Description

有一棵 nnn 個結點的樹,樹上結點從 111nnn 標號。

定義樹上一個連通子圖的權值為最長的區間 [l,r][l,r][l,r] 的長度,滿足標號在 [l,r][l,r][l,r] 之間的結點均在這個連通子圖中。

現在請你求出樹上所有的結點數量不超過 kkk 的連通子圖的權值最大值。

Solution\text{Solution}Solution

大結論題。
做完本題可以水一下這個。

結論:一棵給定的樹,若給出若干關鍵點,將其按照 dfs 序排序后為 a1...ka_{1...k}a1...k?,則它們的最小導出子圖的邊權和為 dis(a1,a2)+dis(a2,a3)+...+dis(ak,a1)dis(a_1,a_2)+dis(a_2,a_3)+...+dis(a_k,a_1)dis(a1?,a2?)+dis(a2?,a3?)+...+dis(ak?,a1?) 的一半。
證明:每條邊都會被算兩遍。(感性理解一下)

有這個結論后,本題就簡單了。二分答案,然后雙指針掃一遍,不斷維護一個 set 計算當前導出圖的邊權和即可,點數就是再加一。

#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1e5+100; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m; struct node{int to,nxt; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt; } int pl[N][20],pos[N],siz[N],tim,dep[N]; void dfs(int x,int fa){pos[x]=++tim;siz[x]=1;dep[x]=dep[fa]+1;pl[x][0]=fa;for(int k=1;pl[x][k-1];k++) pl[x][k]=pl[pl[x][k-1]][k-1];for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==fa) continue;dfs(to,x);siz[x]+=siz[to];}return; } inline int Lca(int x,int y){if(pos[x]<=pos[y]&&pos[y]<=pos[x]+siz[x]-1) return x;for(int k=17;k>=0;k--){int o=pl[x][k];if(!o||(pos[o]<=pos[y]&&pos[y]<=pos[o]+siz[o]-1)) continue;x=pl[x][k];//printf("k=%d x=%d\n",k,x);}return pl[x][0]; } inline int dis(int x,int y){int lca=Lca(x,y);//printf(" dis: x=%d y=%d lca=%d res=%d\n",x,y,lca,dep[x]+dep[y]-2*dep[lca]);return dep[x]+dep[y]-2*dep[lca]; } struct cmp{bool operator ()(const int a,const int b){return pos[a]<pos[b];} }; set<int,cmp>s; set<int,cmp>::iterator it; int now; inline int Pre(int x){it=s.find(x);if(it==s.begin()) return (*s.rbegin());else{it--;return (*it);} } inline int Nxt(int x){it=s.find(x);it++;if(it==s.end()) return (*s.begin());else return (*it); } inline void add(int x){if(s.empty()){s.insert(x);return;}s.insert(x);int pre=Pre(x),nxt=Nxt(x);now-=dis(pre,nxt);now+=dis(pre,x)+dis(x,nxt);return; } inline void del(int x){if(s.size()==1){s.erase(x);return;}int pre=Pre(x),nxt=Nxt(x);now-=dis(pre,x)+dis(x,nxt);now+=dis(pre,nxt);s.erase(x);return; } bool check(int k){now=0;s.clear();for(int i=1;i<=k;i++) add(i);if(now/2+1<=m) return true;//printf("(%d %d) now=%d\n",1,k,now);for(int i=k+1;i<=n;i++){del(i-k);add(i);//printf("(%d %d) now=%d\n",i-k+1,i,now);if(now/2+1<=m) return true;}return false; }signed main(){ #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<n;i++){int x=read(),y=read();addline(x,y);addline(y,x);}dfs(1,0);//printf("lca=%d\n",Lca(2,1));//printf("check=%d\n",check(3));//return 0;int st=1,ed=n;while(st<ed){int mid=(st+ed+1)>>1;if(check(mid)) st=mid;else ed=mid-1;}printf("%d\n",st);return 0; } /* */

總結

以上是生活随笔為你收集整理的CodeForces:372(div1)div373(div2)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。