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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

第四章:枚举 模拟 排序习题 【完结】

發(fā)布時間:2025/3/20 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第四章:枚举 模拟 排序习题 【完结】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

基本熟練掌握。

目錄

  • 1210. 連號區(qū)間數(shù) 【枚舉 】
  • 1236. 遞增三元組 【枚舉 / 前綴和 / hush定址法】
  • 1245. 特別數(shù)的和 【簡單】
  • 1204. 錯誤票據(jù) 【簡單】
  • 466. 回文日期 【枚舉】
  • 787. 歸并排序 【板子題】
  • 1219. 移動距離 【找規(guī)律】
  • 1229. 日期問題 【枚舉】
  • 1231. 航班時間 【模擬】
  • 788. 逆序?qū)Φ臄?shù)量 【板子題】
  • 1241. 外賣店優(yōu)先級 【大模擬題】

1210. 連號區(qū)間數(shù) 【枚舉 】


題目詳解

#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int a[N],n; int main(void) {cin>>n;for(int i=1;i<=n;i++) cin>>a[i];int ans=0;for(int i=1;i<=n;i++){int l=a[i],r=a[i];for(int j=i;j>=1;j--){l=min(l,a[j]);r=max(r,a[j]);if((r-l)==(i-j)) ans++;}}cout<<ans;return 0; }

1236. 遞增三元組 【枚舉 / 前綴和 / hush定址法】


https://www.acwing.com/problem/content/1238/

思路: 找中間的數(shù)組B 因為選B的話 剩下的A和C之間就沒有影響了。
對于數(shù)組中的每一個B 的元素 我們只要統(tǒng)計A中小于它的數(shù)值有多少個,C中大于它的數(shù)值有多少個。
兩者相乘,并求其和就為總的個數(shù)。

以A來說: 首先用一個數(shù)組來統(tǒng)計各個數(shù)據(jù)的個數(shù)。
再用一個數(shù)組 求其前綴和。這樣就可以得到小于B的數(shù)組的元素個數(shù)。

y總的思路就是:
先說A(C和A的方法一樣,就不贅述),用一個數(shù)組來統(tǒng)計各個數(shù)字出現(xiàn)的次數(shù)。
就是定址法。 再用一個前綴和,來統(tǒng)計每個小于等當前位置的所有的數(shù)的出現(xiàn)次數(shù)。
最后通過B的數(shù)的值來找到對應(yīng)的前綴和,即找到了小于B的數(shù)出現(xiàn)的次數(shù)。

1.第一個問題: 為啥要統(tǒng)一加一?
統(tǒng)一加1的目的是為了防止數(shù)組越界。
2.第二個問題: 為啥前綴和的for 是從1~N
其實1~N指的是數(shù)據(jù)范圍內(nèi) 的前綴和。不要以為是 1~n,這只是我們數(shù)的個數(shù),并不是數(shù)值的大小

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring>using namespace std;const int N=100010;int n; int a[N],b[N],c[N]; int cnt[N],s[N];//統(tǒng)計個數(shù) , 前綴和 int at[N],ct[N];//小于B的元素個數(shù) 大于B的元素個數(shù)int main(void) {cin>>n;for(int i=0;i<n;i++) scanf("%d",&a[i]),a[i]++;//統(tǒng)一加1,是為了避免數(shù)組越界for(int i=0;i<n;i++) scanf("%d",&b[i]),b[i]++;for(int i=0;i<n;i++) scanf("%d",&c[i]),c[i]++;for(int i=0;i<n;i++) cnt[a[i]]++;//統(tǒng)計各個數(shù)字出現(xiàn)的個數(shù)for(int i=1;i<N;i++) s[i]=s[i-1]+cnt[i];//統(tǒng)計每個數(shù)字出現(xiàn)次數(shù)的前綴和 s[i] 表示1~i所有的數(shù)出現(xiàn)的次數(shù)的和for(int i=0;i<n;i++) at[i]=s[b[i]-1];//統(tǒng)計小于B的元素的個數(shù)memset(cnt,0,sizeof cnt);memset(s,0,sizeof s);for(int i=0;i<n;i++) cnt[c[i]]++;//for(int i=1;i<N;i++) s[i]=s[i-1]+cnt[i];for(int i=0;i<n;i++) ct[i]=s[N-1]-s[b[i]];long long ans=0;for(int i=0;i<n;i++) ans+=(long long)at[i]*ct[i];cout<<ans<<endl;return 0; } #include<bits/stdc++.h> using namespace std; const int N=1e5+10; int a[N],b[N],c[N],n; int cnt1[N],cnt2[N],aa[N],cc[N]; int s[N],ss[N]; long long int ans=0; int main(void) {cin>>n;for(int i=1;i<=n;i++) cin>>a[i],a[i]++,cnt1[a[i]]++;for(int i=1;i<=n;i++) cin>>b[i],b[i]++;for(int i=1;i<=n;i++) cin>>c[i],c[i]++,cnt2[c[i]]++;for(int i=1;i<N;i++) s[i]=s[i-1]+cnt1[i];for(int i=1;i<N;i++) ss[i]=ss[i-1]+cnt2[i];for(int i=1;i<=n;i++) aa[i]=s[b[i]-1],cc[i]=ss[N-1]-ss[b[i]];for(int i=1;i<=n;i++) ans+=(long long)aa[i]*cc[i];cout<<ans;return 0; }

1245. 特別數(shù)的和 【簡單】

#include<bits/stdc++.h> using namespace std; int sum,n; bool judge(int x) {while(x){int t=x%10;if(t==2||t==0||t==1||t==9) return true;x/=10;}return false; } int main(void) {cin>>n;for(int i=1;i<=n;i++) if(judge(i)) sum+=i;cout<<sum;return 0; }

1204. 錯誤票據(jù) 【簡單】

#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,a[N],k,cnt[N]; int main(void) {cin>>n;while(cin>>a[k++]);sort(a,a+k);int l,r;for(int i=0;i<k;i++){if(i&&a[i]-a[i-1]>1) l=a[i]-1;cnt[a[i]]++;if(cnt[a[i]]>1) r=a[i];}cout<<l<<" "<<r;return 0; }

466. 回文日期 【枚舉】


https://www.acwing.com/problem/content/468/
暴力方法: 超時了

#include<iostream> #include<string> #include<algorithm> using namespace std; int m[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int data1,data2; int ans; struct data {int year;int month;int day; }d1,d2; bool judge(int n) {if(n%400==0||n%4==0&&n%100!=0) return true;else return false; } int main(void) {cin>>data1>>data2;d1.year=data1/10000;d2.year=data2/10000;d1.month=data1%10000/100;d2.month=data2%10000/100;d1.day=data1%100;d2.day=data2%100;if(data1==data2)//如果起始和結(jié)束的是同一天,特判。不特判的話后面的do while 會陷入死循環(huán){string a;a=to_string(d1.year); if(d1.month<10)a=a+'0'+to_string(d1.month);elsea=a+to_string(d1.month);if(d1.day<10)a=a+'0'+to_string(d1.day);elsea=a+to_string(d1.day);int temp=a.size();for(int i=0;i<temp/2;i++){if(a[i]!=a[temp-1-i]){cout<<0<<endl;return 0;}}cout<<1<<endl;return 0;}do//因為包含起始和結(jié)束的日期所以用 do while{bool flag=true;string a;a=to_string(d1.year); if(d1.month<10)a=a+'0'+to_string(d1.month);elsea=a+to_string(d1.month);if(d1.day<10)a=a+'0'+to_string(d1.day);elsea=a+to_string(d1.day);int temp=a.size();for(int i=0;i<temp/2;i++){if(a[i]!=a[temp-1-i]){flag=false;}}d1.day++;if(judge(d1.year)){m[2]=29;}if(d1.day>m[d1.month]){d1.month++;d1.day=1;}if(d1.month==13){d1.month=1;d1.year++;}m[2]=28;if(flag)ans++;}while(d1.year!=d2.year||d1.month!=d2.month||d1.day!=d2.day);cout<<ans<<endl;return 0; }

巧妙的思路: 我們只要枚舉前4位,組成回文數(shù)字,看是不是合法的日期就可以了。

#include<iostream> using namespace std;int m[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};bool judge(int n) {if(n%400==0||n%4==0&&n%100!=0) return true;else return false; }int data1,data2; int ans;bool check(int n) {if(judge(n/10000)) m[2]=29;int month=n%10000/100;int day=n%100;if(month==0||month>=13) return false;if(day==0||day>m[month]) return false;return true; } int main(void) {cin>>data1>>data2;for(int i=1000;i<=10000;i++){int temp=i;int x=i;for(int j=0;j<4;j++)//回文數(shù)字{temp=temp*10+x%10;x/=10;}if(temp>=data1&&temp<=data2&&check(temp)){ans++;}}cout<<ans<<endl;return 0; } #include<bits/stdc++.h> using namespace std; int l,r,ans; bool flag; int m[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; bool judge(int x) {if( (x%400==0) || (x%4==0&&x%100!=0)) return true;else return false; } bool check(int x) {string s=to_string(x);string temp=s;reverse(temp.begin(),temp.end());s+=temp;int year=stoi(s.substr(0,4));if(year<1000) return false;int month=stoi(s.substr(4,2));if(month==0||month>=13) return false;if(month==2&&judge(year)) m[2]=29;int day=stoi(s.substr(6,2));if(day<=0||day>m[month]) return false;x=stoi(s);if(x>=l&&x<=r) return true;else return false;m[2]=28; } int main(void) {cin>>l>>r;for(int i=1000;i<=9999;i++){if(check(i)) ans++;if(flag) break;}cout<<ans;return 0; }

787. 歸并排序 【板子題】


https://www.acwing.com/problem/content/789/

#include<cstdio> using namespace std; const int N=100010; int a[N]; int tmp[N]; void merge_sort(int q[],int l,int r) {if(l>=r) return;//說明已經(jīng)分成一個一個的了int mid=l+r>>1;merge_sort(q,l,mid),merge_sort(q,mid+1,r);int k=0;int i=l;//左區(qū)間的頭 int j=mid+1; //右區(qū)間的頭while(i<=mid&&j<=r){if(q[i]<=q[j]) tmp[k++]=q[i++];else tmp[k++]=q[j++];} while(i<=mid) tmp[k++]=q[i++];//合并剩下的 while(j<=r) tmp[k++]=q[j++];for(i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];//記錄當前的狀態(tài) } int main(void) {int n; scanf("%d",&n);for(int i=0;i<n;i++) scanf("%d",&a[i]);merge_sort(a,0,n-1);for(int i=0;i<n;i++) printf("%d ",a[i]);puts("");return 0; }

1219. 移動距離 【找規(guī)律】


思路: 找下標和對應(yīng)數(shù)的規(guī)律。

巧妙的一點在于: 整體減1。這樣就少了很多的特判。
例如: 如果不整體減1 , 1的行號=1/6=0 但是 6的行號=6/6=1 這顯然不行,我們還得進一步的判斷。
但是如果整體減1后 1-1=0/6=0 6-1=5/6=0 這樣就少了特判。十分的方便。
一個字: 秒!

#include<iostream> #include<string> #include<cmath> using namespace std; int main(void) {int w,m,n; cin>>w>>m>>n;int x1,y1,x2,y2;m--,n--;//統(tǒng)一減1x1=m/w;x2=n/w;if(x1%2==0)y1=m%w;elsey1=w-1-m%w;if(x2%2==0)y2=n%w;elsey2=w-1-n%w;cout<<abs(x1-x2)+abs(y1-y2)<<endl;return 0; }

精簡版:

#include<iostream> #include<string> #include<cmath> using namespace std; int main(void) {int w,m,n; cin>>w>>m>>n;int x1,y1,x2,y2;m--,n--;x1=m/w;x2=n/w;y1=m%w;y2=n%w;if(x1&1) y1=w-1-m%w;//行數(shù)是奇數(shù)if(x2&1) y2=w-1-n%w;//行數(shù)是奇數(shù) cout<<abs(x1-x2)+abs(y1-y2)<<endl;return 0; } #include<bits/stdc++.h> using namespace std; int w,m,n; int x,y,xx,yy; int main(void) {cin>>w>>m>>n;x=(m-1)/w;xx=(n-1)/w;if(x%2==0) y=(m-w*x)%(w+1)-1;else y=w-(m-w*x)%(w+1);if(xx%2==0) yy=(n-w*xx)%(w+1)-1;else yy=w-(n-w*xx)%(w+1);cout<<abs(x-xx)+abs(y-yy);return 0; }

1229. 日期問題 【枚舉】


https://www.acwing.com/problem/content/1231/

模擬寫法:

#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; int m[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; bool judge(int year) {if(year%400==0|| (year%4==0&&year%100!=0) ) return true;else return false; } struct date {int year;int month;int day; }d[10]; bool cmp(date a,date b) {if(a.year==b.year){if(a.month==b.month){return a.day<b.day;}return a.month<b.month;}return a.year<b.year; } int main(void) {int x1,x2,x3;scanf("%d/%d/%d",&x1,&x2,&x3);int sum=x1+1900;//x1為年 x2為月 x3為日 int number=0;if(sum>=1960&&sum<=2059){if(judge(sum))m[2]=29; if(x2>=1&&x2<=12){if(x3>=1&&x3<=m[x2]){d[number].year=sum;d[number].month=x2;d[number++].day=x3;}}m[2]=28;}sum=x1+2000;if(sum>=1960&&sum<=2059){if(judge(sum))m[2]=29; if(x2>=1&&x2<=12){if(x3>=1&&x3<=m[x2]){d[number].year=sum;d[number].month=x2;d[number++].day=x3;}}m[2]=28;}int sum2=x3+1900;//x1為月 x2為日 x3為年 if(sum2>=1960&&sum2<=2059){if(judge(sum2))m[2]=29; if(x1>=1&&x1<=12){if(x2>=1&&x2<=m[x1]){d[number].year=sum2;d[number].month=x1;d[number++].day=x2;}}m[2]=28;}sum2=x3+2000;if(sum2>=1960&&sum2<=2059){if(judge(sum2))m[2]=29; if(x1>=1&&x1<=12){if(x2>=1&&x2<=m[x1]){d[number].year=sum2;d[number].month=x1;d[number++].day=x2;}}m[2]=28;}int sum3=x3+1900;//x1為日 x2為月 x3為年 if(sum3>=1960&&sum3<=2059){if(judge(sum3))m[2]=29; if(x2>=1&&x2<=12){if(x1>=1&&x1<=m[x2]){d[number].year=sum3;d[number].month=x2;d[number++].day=x1;}}m[2]=28;}sum3=x3+2000;if(sum3>=1960&&sum3<=2059){if(judge(sum3))m[2]=29; if(x2>=1&&x2<=12){if(x1>=1&&x1<=m[x2]){d[number].year=sum3;d[number].month=x2;d[number++].day=x1;}}m[2]=28;}sort(d,d+number,cmp);printf("%d-%02d-%02d\n",d[0].year,d[0].month,d[0].day);for(int i=1;i<number;i++) {//去重 if( (d[i].year==d[i-1].year) && (d[i].month==d[i-1].month) && (d[i].day==d[i-1].day) )continue;printf("%d-%02d-%02d\n",d[i].year,d[i].month,d[i].day);}return 0; }

枚舉寫法: 操作簡單,枚舉所有的日期看是不是,是合法的日期,再看是不是和我們輸入的日期相匹配。

#include<cstdio> #include<iostream> #include<string> using namespace std; int m[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int x1,x2,x3; bool judge(int n) {if(n%400==0|| (n%4==0&&n%100!=0) ) return true;else return false; } bool check(int a,int b,int c) {if(a==x1&&b==x2&&c==x3)return true;return false; } int main(void) {scanf("%d/%d/%d",&x1,&x2,&x3);for(int i=19600101;i<=20591231;i++){int year=i/10000;int month=i%10000/100;int day=i%100;if(judge(year)) m[2]=29;if(month>=1&&month<=12&&day>=1&&day<=m[month])//日期合法 if(check(year%100,month,day)||check(month,day,year%100)||check(day,month,year%100))//匹配 {printf("%d-%02d-%02d\n",year,month,day);}m[2]=28;}return 0; }

1231. 航班時間 【模擬】


https://www.acwing.com/problem/content/1233/

公式: 飛行時間=(兩次時間差的和)/2

飛機在飛,由于人為規(guī)定的時區(qū)導(dǎo)致好像時間變慢或者快了(實際上沒有)。這里很像我們高中物理學(xué)的運動學(xué)知識,我們可以假設(shè)一個場景——船在不平靜水面行駛,船從一個點出發(fā)行駛了s路程后返回原點(期間船速不變),然后告訴我們來回整個過程回到原點的時間是t,問船在靜水中行駛s路程需要多長時間。我們可以以水為參考系,那么顯然這個時間為 t/2。

方法一:

#include<cstdio> #include<iostream> #include<string>using namespace std;int get_second(int h,int m,int s)//表示從00:00:00 到當前時間的秒數(shù)和 {return h*3600+m*60+s; }int get_time() {string line;getline(cin,line);if(line.back()!=')') line+="(+0)";int h1,m1,s1,h2,m2,s2,d;sscanf(line.c_str(),"%d:%d:%d %d:%d:%d (+%d)",&h1,&m1,&s1,&h2,&m2,&s2,&d);return get_second(h2,m2,s2)-get_second(h1,m1,s1)+d*24*3600; }int main(void) {int n; scanf("%d",&n);string line;getline(cin,line);while(n--){int time=(get_time()+get_time())/2;int hour=time/3600,minute=time%3600/60,second=time%60;printf("%02d:%02d:%02d\n",hour,minute,second);}return 0; }

方法二:

#include<bits/stdc++.h> using namespace std; int getTime(void) {int h1,m1,s1,h2,m2,s2,d=0;scanf("%d:%d:%d %d:%d:%d (+%d)",&h1,&m1,&s1,&h2,&m2,&s2,&d);int time=d*24*3600+h2*3600+m2*60+s2-(h1*3600+m1*60+s1);return time; } int main() {int t;scanf("%d",&t);for(int i = 0; i < t; i++){int time1=getTime();int time2=getTime();int t=(time1+time2)/2;printf("%02d:%02d:%02d\n", t/3600, t/60%60, t%60);}return 0; } #include<bits/stdc++.h> using namespace std; int n; int get() {string s; getline(cin,s);int a,b,c,aa,bb,cc;sscanf(s.c_str(),"%d:%d:%d %d:%d:%d",&a,&b,&c,&aa,&bb,&cc);int sum=0;if(s.find('+')!=-1){string ss=s.substr(s.find('+')+1,1);aa+=stoi(ss)*24;}sum=aa*3600+bb*60+cc-a*3600-b*60-c;return sum; } int main(void) {cin>>n;string s; getline(cin,s);while(n--){int sum=(get()+get())/2;printf("%02d:%02d:%02d\n",sum/3600,(sum%3600)/60,sum%60);}return 0; }

788. 逆序?qū)Φ臄?shù)量 【板子題】

https://www.acwing.com/solution/content/2103/

思路: 就是用到了歸并排序。歸并排序有一個特點就是分割的區(qū)間都是有序的,即遞增的。

#include<cstdio> #include<iostream> #define LL long long using namespace std; const int N=100100; int a[N],temp[N]; int n; LL res; void merge_sort(int q[],int l,int r) {if(l>=r) return;int mid=l+r>>1;merge_sort(q,l,mid),merge_sort(q,mid+1,r);int k=0,i=l,j=mid+1;while(i<=mid&&j<=r) {if(a[i]<=a[j]) temp[k++]=a[i++];else{res+=mid-i+1;//重中之重temp[k++]=a[j++];}}while(i<=mid) temp[k++]=a[i++];while(j<=r) temp[k++]=a[j++];for(i=l,j=0;i<=r;i++,j++) a[i]=temp[j]; } int main(void) {scanf("%d",&n);for(int i=0;i<n;i++) scanf("%d",&a[i]);merge_sort(a,0,n-1); cout<<res;return 0; }

為啥 res+=mid-i-1 ? 這是因為:
數(shù)組a中的i ~ mid的數(shù)組是遞增數(shù)組, 觸發(fā)條件是a[i] > a[j],所以i~mid中的數(shù)字都比當前a[j]大,
所以左邊i ~ mid的數(shù)組中有 mid - i + 1個數(shù)比a[j] 大

1241. 外賣店優(yōu)先級 【大模擬題】

#include<bits/stdc++.h> using namespace std; const int N=1e6+10; int n,m,t,ans; map<int,vector<int> >mp; int st[N]; int main(void) {cin>>n>>m>>t;while(m--){int a,b; cin>>a>>b;mp[b].push_back(a);}for(auto i=1;i<=n;i++){sort(mp[i].begin(),mp[i].end());int score=0,index=0;for(int j=0;j<mp[i].size();j++){int cnt=1;int k=j;while( ( (k+1) < mp[i].size() ) && (mp[i][k]==mp[i][k+1]) ) cnt++,k++;score-=(mp[i][j]-index-1);if(score<0) score=0;if(score<=3) st[i]=0;score+=cnt*2;index=mp[i][j];if(score>5) st[i]=1;j=k;}if(index<t) score-=(t-index);if(score<=3) st[i]=0;}for(int i=1;i<=n;i++) ans+=st[i];cout<<ans;return 0; }

總結(jié)

以上是生活随笔為你收集整理的第四章:枚举 模拟 排序习题 【完结】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。