模拟 AcWing1210 连号区间数量 题意 1210. 连号区间数 - AcWing题库
概括:给定排列的数组 求连号区间的个数
思路
首先,有个概念:排列 ,一般地,从n个不同元素 中取出m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列。
既然从a[L]到a[R]数组内的元素如果排序后严格逐个递增,那么必有max-min=R-L ;题目已经说了是排列,所以不可能有相同的多个元素
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <bits/stdc++.h> using namespace std;const int N=10005 ;int n,a[N];int main () { scanf ("%d" ,&n); int ans=0 ; for (int i=1 ;i<=n;i++) scanf ("%d" ,&a[i]); for (int i=1 ;i<=n;i++){ int maxx=a[i],minn=a[i]; for (int j=i;j<=n;j++){ maxx = max (maxx,a[j]); minn = min (minn,a[j]); if (maxx-minn == j-i) ans++; } } printf ("%d\n" ,ans); }
AcWing1236 递增三元组 题意 1236. 递增三元组 - AcWing题库
思路
首先考虑暴力求解,但至少三重循环,不太行,考虑如何优化:
根据数据范围 1e5 反推,时间复杂度最多时nlogn的,并且至少会有一层遍历n,所有考虑logn的算法
所以 可以循环遍历Bi,然后在A中找小于Bi的,在C中找大于Bi的;考虑用 前缀和 或者 二分 的方法
要求的是满足条件的三元组个数,则只需要 找到A中小于Bi个数,C中大于Bi的个数,相乘即可
细节 :
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <bits/stdc++.h> using namespace std;typedef long long LL;const int N=1e5 +5 ;int n,a[N],b[N],c[N],sa[N],sc[N],s[N],cnt[N]; int main () { scanf ("%d" ,&n); for (int i=1 ;i<=n;i++) scanf ("%d" ,&a[i]),a[i]++; for (int i=1 ;i<=n;i++) scanf ("%d" ,&b[i]),b[i]++; for (int i=1 ;i<=n;i++) scanf ("%d" ,&c[i]),c[i]++; for (int i=1 ;i<=n;i++) cnt[a[i]]++; for (int i=1 ;i<N;i++) s[i]=s[i-1 ]+cnt[i]; for (int i=1 ;i<=n;i++) sa[i]=s[b[i]-1 ] ; memset (s,0 ,sizeof s); memset (cnt,0 ,sizeof cnt); for (int i=1 ;i<=n;i++) cnt[c[i]]++; for (int i=1 ;i<N;i++) s[i]=s[i-1 ]+cnt[i]; for (int i=1 ;i<=n;i++) sc[i]=s[N-1 ]-s[b[i]]; LL ans=0 ; for (int i=1 ;i<=n;i++) ans=ans+(LL)sa[i]*sc[i]; cout<<ans<<endl; }
AcWing1204 错误票据 题意 1204. 错误票据 - AcWing题库
思路 题目很简单,主要是复习一下输入流
getline() 的用法:接受一个字符串,可以接受空格并输出
1 2 3 string str; getline (cin,str); cout<<str<<endl;
当同时使用cin>>
和getline(cin,str)
的时候,在cin>>
输入完成之后,getline(cin,str)
(str是真正想要的串)之前,需要先 getline(cin,str)
(这个str是一个打算用来存储回车符的串);将回车符从输入流缓存中清除
1 2 3 4 5 int n;string line; cin>>n; getline (cin,line);getline (cin,line);
stringstream 的用法:主要用于将一个string串分割
1 2 3 4 5 6 7 8 string s; stringstream ss; int a b c;getline (cin,s);ss.clear (); ss.str (s); ss>>a>>b>>c; ss.fail ();
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std;const int N=105 ;int cnt,n;int a[N*N];int main () { ios::sync_with_stdio (false ); cin>>cnt; string line; getline (cin,line); while (cnt--){ getline (cin,line); stringstream ss; ss.str (line); while (ss>>a[n]) n++; } sort (a,a+n); int res0,res1; for (int i=1 ;i<n;i++){ if (a[i]==a[i-1 ]) res0=a[i]; else if (a[i]==a[i-1 ]+2 ) res1=a[i-1 ]+1 ; } cout<<res1<<' ' <<res0<<endl; }
AcWing466 回文日期 题意 水题
思路 简单,但要复习一下之前忘记的东西
代码 自己直接模拟的,比较冗余;看了下y总的思路:因为只有8位数字,所以只需要枚举左半边一万个数,然后生成右半边对称的数,针对每个数判断是否合法以及是否在范围内即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include <bits/stdc++.h> using namespace std;struct D { int year,month,day; }; D getDate (string a) { int year=atoi (a.substr (0 ,4 ).c_str ()); int month=atoi (a.substr (4 ,2 ).c_str ()); int day = atoi (a.substr (6 ,2 ).c_str ()); D date={year,month,day}; return date; } bool isLeapYear (int y) { if ((y%4 ==0 &&y%400 !=0 )|| (y%400 ==0 )) return 1 ; else return 0 ; } int isValid (int y,int m,int d) { if (m<=0 ||m>=13 ||d<=0 ||d>31 ) return 0 ; if (m==4 ||m==6 ||m==9 ||m==11 ){ if (d>30 ) return 0 ; } if (m==2 ){ if (isLeapYear (y)&&d>29 ) return 0 ; else if ((!isLeapYear (y))&&(d>28 )) return 0 ; } return 1 ; } int ans;int main () { int ay,am,ad; int by,bm,bd; string a,b; cin>>a>>b; ay=getDate (a).year; am=getDate (a).month; ad=getDate (a).day; by=getDate (b).year; bm=getDate (b).month; bd=getDate (b).day; int m=(ay%10 )*10 +(ay/10 %10 ); int d=(ay/100 %10 )*10 +ay/1000 %10 ; if (isValid (ay,m,d)){ if (m>am) ans++; else if (m==am&&d>=ad) ans++; } m=(by%10 )*10 +(by/10 %10 ); d=(by/100 %10 )*10 +by/1000 %10 ; if (isValid (by,m,d)){ if (m>bm) ans++; else if (m==bm&&d>=bd&&(a!=b)) ans++; } for (int year=ay+1 ;year<=by-1 ;year++){ int month=(year%10 )*10 +(year/10 %10 ); int day=(year/100 %10 )*10 +year/1000 %10 ; ans+=isValid (year,month,day); } cout<<ans<<endl; }
AcWing1229 日期问题 题意 思路 直接暴力求解,对字符串处理判断,需要考虑重复和排序的问题
y总的思路很好:枚举从起始到终止 ,判断是否等于输入的日期,就可以避免排序和重复问题
水题,但是复习一下:
日期的格式化输入输出 采用scanf printf比cin和cout方便
数据输出最低两位,不足的高位补0输出
1 2 printf ("%02d" ,3 ); printf ("%2d" ,312312 );
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <bits/stdc++.h> using namespace std;int days[13 ]={0 ,31 ,28 ,31 ,30 ,31 ,30 ,31 ,31 ,30 ,31 ,30 ,31 };bool check (int y,int m,int d) { if (m==0 ||m>12 ) return 0 ; if (d==0 ) return 0 ; if (m!=2 ){ if (d>days[m]) return 0 ; }else { int leap=(y%100 !=0 &&y%4 ==0 )||(y%400 ==0 ); if (d>28 +leap) return 0 ; } return 1 ; } int main () { int a,b,c; scanf ("%d/%d/%d" ,&a,&b,&c); for (int date=19600101 ;date<=20591231 ;date++){ int y=date/10000 ,m=date%10000 /100 ,d=date%100 ; if (check (y,m,d)){ if (y%100 ==a&&m==b&&d==c|| m==a&&d==b&&y%100 ==c|| d==a&&m==b&&y%100 ==c ) printf ("%d-%02d-%02d\n" ,y,m,d); } } }
AcWing1231 航班时间
1 2 3 4 5 6 7 8 9 10 11 12 13 string a="abcd" ; 1. 获取字符串最后一个字符auto b=a.back (); 2. 修改字符串最后一个字符a.back ()='!' ; 3. 获取字符串第一个字符auto b=a.front (); 4. 修改字符串第一个字符a.front ()='!' ;
sscanf
从一个字符串中读进于指定格式 相符的数据。利用它可以从字符串中取出整数、浮点数和字符串。
sscanf和scanf的区别:scanf是以键盘作为输入源,sscanf是以字符串作为输入源。
1 2 3 4 5 int sscanf (const char *str, const char *format,......) ;sscanf (line.c_str (),"%d:%d:%d %d:%d:%d (+%d)" ,&h1,&m1,&s1,&h2,&m2,&s2,&d);
去乘起飞时间+航行时间+时差=去乘降落时间 回程起飞时间+航行时间-时差=回程降落时间 航行时间 = (去乘降落时间-去乘起飞时间+回程降落时间-回程起飞时间)/2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <bits/stdc++.h> using namespace std;int get_seconds (int h,int m,int s) { 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_seconds (h2,m2,s2)-get_seconds (h1,m1,s1)+d*24 *3600 ; } int main () { int g;cin>>g; string line; getline (cin,line); while (g--){ int time=(get_time ()+get_time ())>>1 ; int h=time/3600 ,m=time%3600 /60 ,s=time%60 ; printf ("%02d:%02d:%02d\n" ,h,m,s); } return 0 ; }
AcWing446 字符串处理 题意 446. 统计单词数 - AcWing题库
思路 代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <bits/stdc++.h> using namespace std;int main () { string a,b; getline (cin,a);getline (cin,b); transform (a.begin (),a.end (),a.begin (),::tolower); transform (b.begin (),b.end (),b.begin (),::tolower); a=" " +a+" " ; b=" " +b+" " ; int pos=b.find (a); int idx=0 ,res=0 ; if (pos!=-1 ){ idx=pos; while (pos!=-1 ){ res++; pos=b.find (a,pos+1 ); } }else { cout<<-1 <<endl;return 0 ; } cout<<res<<' ' <<idx<<endl; return 0 ; }
排序 快速排序 sort()数据量大时采用快排,分段递归排序,一旦分段后的数据量小于某个门槛,为避免快排的递归调用带来过大的额外负荷,就改用插入排序。如果递归层次过深,还会改用堆排序,时间复杂度$nlog_{2}n$
基本思想 模板 1 2 3 4 5 6 7 8 9 10 11 12 13 void quick_sort (int q[],int l,int r) { if (l>=r) return ; int i=l-1 ,j=r+1 ,x=q[l+r>>1 ]; while (i<j){ do i++;while (q[i]<x); do j--;while (q[j]>x); if (i<j) swap (q[i],q[j]); } quick_sort (q,l,j),quick_sort (q,j+1 ,r); }
归并排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int q[N],tmp[N];void merge_sort (int l,int r) { if (l>=r) return ; int mid=l+r>>1 ; merge_sort (l,mid),merge_sort (mid+1 ,r); int k=0 ,i=l,j=mid+1 ; 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 (int i=l,j=0 ;i<=r;i++,j++) q[i]=tmp[j]; }