Codeforces 水题糊做#1
感觉自己对于CF的Div2CD难度的题做的还不够好,所以开个坑练习一下吧.
6/20
1.Codeforces 1006D. Two Strings Swaps
根据题意规则大力分类讨论。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <queue> 7 #include <map> 8 #define ll long long 9 #define out(a) printf("%d",a) 10 #define writeln printf("\n") 11 const int N=1e5+50; 12 using namespace std; 13 int n; 14 char s1[N],s2[N]; 15 int ans; 16 int read() 17 { 18 int s=0,t=1; char c; 19 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 20 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 21 return s*t; 22 } 23 ll readl() 24 { 25 ll s=0,t=1; char c; 26 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 27 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 28 return s*t; 29 } 30 int main() 31 { 32 n=read(); 33 scanf("%s",s1+1); scanf("%s",s2+1); 34 if (n&1){ 35 if (s1[n/2+1]!=s2[n/2+1]) ans++; 36 } 37 for (int i=1;i<=n/2;i++){ 38 if (s1[i]==s1[n-i+1]&&s2[i]==s2[n-i+1]) continue; 39 if (s1[i]==s2[i]&&s1[n-i+1]==s2[n-i+1]) continue; 40 if (s1[i]==s2[n-i+1]&&s2[i]==s1[n-i+1]) continue; 41 if (s1[i]==s1[n-i+1]&&s2[i]!=s2[n-i+1]) { 42 ans+=2; 43 if (s1[i]==s2[i]||s1[n-i+1]==s2[n-i+1]) ans--; continue; 44 } 45 if (s2[i]==s2[n-i+1]&&s1[i]!=s1[n-i+1]) { 46 ans++; continue; 47 } 48 if (s1[i]==s2[i]&&s1[n-i+1]!=s2[n-i+1]) { 49 ans++; continue; 50 } 51 if (s1[i]!=s2[i]&&s1[n-i+1]==s2[n-i+1]) { 52 ans++; continue; 53 } 54 if (s1[i]==s2[n-i+1]&&s2[i]!=s1[n-i+1]) { 55 ans++; continue; 56 } 57 if (s2[i]==s1[n-i+1]&&s1[i]!=s2[n-i+1]) { 58 ans++; continue; 59 } 60 ans+=2; 61 } 62 out(ans); 63 return 0; 64 } 65 66
2.Codeforces 1005C. Summarize to the Power of Two
n个数,对于一个数a[i],如果没有a[j](i!=j)使得a[i]+a[j]为2的幂次方则删去,求要删去多少个数.
读入的时候把数都扔到map里,对于一个数枚举2的幂次方并减去这个数得到num,在map里查询num是否存在.需要注意的是当num==a[i]时要判断a[i]出现次数是否大于1.
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <queue> 7 #include <map> 8 #define ll long long 9 #define out(a) printf("%d",a) 10 #define writeln printf("\n") 11 const int N=1e5+20050; 12 using namespace std; 13 map<int,int>cnt; 14 int n; 15 int a[N]; 16 int num,ans; 17 bool flag; 18 int read() 19 { 20 int s=0,t=1; char c; 21 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 22 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 23 return s*t; 24 } 25 ll readl() 26 { 27 ll s=0,t=1; char c; 28 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 29 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 30 return s*t; 31 } 32 int main() 33 { 34 n=read(); 35 for (int i=1;i<=n;i++) 36 a[i]=read(),cnt[a[i]]++; 37 for (int i=1;i<=n;i++){ 38 flag=false; 39 for (int j=30;j>=0;j--){ 40 num=1<<j; 41 if (cnt.count(num-a[i])>0) { 42 flag=true; 43 if ((a[i]<<1)==num) { 44 if (cnt[a[i]]==1) ans++; 45 } 46 break; 47 } 48 } 49 if (flag) continue; 50 ans++; 51 } 52 out(ans); 53 return 0; 54 } 55
3.Codeforces 1005E1. Median on Segments (Permutations Edition)
思维好题啊QAQ
给一个1到n的排列和一个数k,求中位数为k的区间有多少个.(区间大小m为偶数时,中位数为第m/2个数)
经典套路就是把等于k的看做0,小于k看做-1,大于k看做1,然后计算一遍前缀和.
那么只要计算多少个区间和为0或和为1即可.
和为0很好理解,那么为什么和为1也要计算呢?
证明一波:由于区间一定包含k这个数,所以区间前缀和数组中一定有0,当区间大小为奇数时,区间和为0说明-1和1数量相等,此时k为中位数,区间大小为偶数时,由于含有一个0,所以-1和1的数量不可能相等,也就是和不可能为0,因为中位数是向下取整,1的数量要比-1数量多1,即和为1.
做到这里就不会了。。n2复杂度是爆炸的.
然后我还是看了一丢丢题解。。
因为区间包含k,我们不妨把区间看做a+k+b的形式(当然a,b可以是空集),预处理出右边区间b和k的前缀和数组扔到map里面,然后枚举左区间map查询与左区间的前缀和数相等或相差1的个数.
答案会爆int,所以记得开long long.
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <queue> 7 #include <map> 8 #define ll long long 9 #define out(a) printf("%lld",a) 10 #define writeln printf("\n") 11 const int N=2e5+50; 12 using namespace std; 13 map<int,int>cnt; 14 int n,k; 15 int a[N],b[N],sum[N]; 16 int num; 17 ll ans; 18 int read() 19 { 20 int s=0,t=1; char c; 21 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 22 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 23 return s*t; 24 } 25 ll readl() 26 { 27 ll s=0,t=1; char c; 28 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 29 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 30 return s*t; 31 } 32 int main() 33 { 34 n=read(),k=read(); 35 for (int i=1;i<=n;i++){ 36 a[i]=read(); 37 if (a[i]>k) b[i]=1; 38 else if (a[i]<k) b[i]=-1; 39 if (a[i]==k) num=i; 40 sum[i]=sum[i-1]+b[i]; 41 if (i>=num&&num) cnt[sum[i]]++; 42 } 43 for (int i=0;i<=num-1;i++) 44 ans+=cnt[sum[i]]+cnt[sum[i]+1]; 45 out(ans); 46 return 0; 47 } 48
4.Codeforces 996D. Suit and Tie
一到n的数,每种数有两个,求交换相邻位置的数使得数字相同的数位置相邻.
考虑两个相同数相邻最少也是他们位置差的绝对值减1,这样直接交换的话并不会改变其他数的顺序,甚至会使原来隔一个数的情况变得相邻,也就是说直接交换答案不会增加甚至会减少.
那么扫一遍交换位置统计答案即可.
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <queue> 7 #include <map> 8 #define ll long long 9 #define out(a) printf("%d ",a) 10 #define writeln printf("\n") 11 const int N=1e5+50; 12 using namespace std; 13 int n,num,ans=0; 14 int a[N],cnt[N]; 15 int read() 16 { 17 int s=0,t=1; char c; 18 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 19 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 20 return s*t; 21 } 22 ll readl() 23 { 24 ll s=0,t=1; char c; 25 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 26 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 27 return s*t; 28 } 29 int main() 30 { 31 n=read(); 32 for (int i=1;i<=2*n;i++) 33 a[i]=read(); 34 for (int i=1;i<=2*n;i+=2){ 35 if (a[i]!=a[i+1]){ 36 for (int j=i+1;j<=2*n;j++) 37 if (a[j]==a[i]){ 38 num=j; break; 39 } 40 ans+=num-i-1; 41 for (int j=num;j>i+1;j--) 42 swap(a[j],a[j-1]); 43 } 44 } 45 out(ans); 46 return 0; 47 }
求有多少个由0组成的L。
如果出现竖着的两个0在同一列,贪心优先考虑往左边找再往右边找,统计答案.
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <queue> 7 #include <map> 8 #define ll long long 9 #define out(a) printf("%d ",a) 10 #define writeln printf("\n") 11 const int N=1e5+50; 12 using namespace std; 13 int n,len; 14 int ans; 15 char s[2][N]; 16 bool flag; 17 int read() 18 { 19 int s=0,t=1; char c; 20 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 21 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 22 return s*t; 23 } 24 ll readl() 25 { 26 ll s=0,t=1; char c; 27 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 28 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 29 return s*t; 30 } 31 int main() 32 { 33 scanf("%s",s[0]); 34 scanf("%s",s[1]); 35 len=strlen(s[0]); 36 for (int i=0;i<len;i++) 37 if (s[0][i]=='0'&&s[1][i]=='0'){ 38 flag=false; 39 for (int j=0;j<2;j++){ 40 if (s[j][i-1]=='0') { 41 ans++,s[j][i-1]='X',flag=true; 42 break; 43 } 44 } 45 if (flag) s[0][i]=s[1][i]='X'; 46 else { 47 for (int j=0;j<2;j++){ 48 if (s[j][i+1]=='0') { 49 ans++,s[j][i+1]='X',flag=true; 50 break; 51 } 52 } 53 if (flag) s[0][i]=s[1][i]='X'; 54 } 55 } 56 out(ans); 57 return 0; 58 }
6.Codeforces 1015D. Walking Between Houses
有1~n的房子,求走k个回合步数刚好为s的方案.
略带思维的贪心题,大概就是先把大步的走完,然后剩下的一步步走.
细节很多也说不清楚,看代码吧==
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #include <queue> 7 #include <map> 8 #define ll long long 9 #define out(a) printf("%lld ",a) 10 #define writeln printf("\n") 11 const int N=1e5+50; 12 using namespace std; 13 ll n,m,k,x,p,num,now,a,b,c; 14 ll ans=0; 15 ll s; 16 int read() 17 { 18 int s=0,t=1; char c; 19 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 20 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 21 return s*t; 22 } 23 ll readl() 24 { 25 ll s=0,t=1; char c; 26 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 27 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 28 return s*t; 29 } 30 int main() 31 { 32 n=readl(),k=readl(),s=readl(); 33 if (k==s) { 34 puts("YES"); 35 for (int i=1;i<=k;i++) 36 if (i&1) cout<<2<<' '; 37 else cout<<1<<' '; 38 return 0; 39 } 40 if (k>s||(n-1)*k<s){ 41 puts("NO"); return 0; 42 } 43 else { 44 puts("YES"); now=x=1; 45 a=s/(n-1); b=s-a*(n-1); c=k-a;//剩c回合可走,还有b步要走 46 if (b>=c) { 47 for (int i=1;i<=a;i++) 48 if (i&1) out(n),now=n,x=-1; 49 else out(1),now=1,x=1; 50 if (b!=c) { 51 c--; now+=(b-c)*x; out(now); 52 } 53 for (int i=1;i<=c;i++) 54 if (now<n) { 55 if (i&1) out(now+1); 56 else out(now); 57 } 58 else if (now==n){ 59 if (i&1) out(now-1); 60 else out(now); 61 } 62 } 63 else { 64 while (b<c){ 65 a--; b+=n-1; 66 c++; 67 } 68 for (int i=1;i<=a;i++) 69 if (i&1) out(n),now=n,x=-1; 70 else out(1),now=1,x=1; 71 if (b!=c) { 72 c--; now+=(b-c)*x; out(now);} 73 for (int i=1;i<=c;i++) 74 if (now<n) { 75 if (i&1) out(now+1); 76 else out(now); 77 } 78 else if (now==n){ 79 if (i&1) out(now-1); 80 else out(now); 81 } 82 } 83 } 84 return 0; 85 }