〖补〗: Gym 102411 / ICPC 2019 North-Western Russia
M - Managing Difficulties Gym - 102411M
题意:
求满足 a[j]−a[i]=a[k]−a[j]的i,j,k有几组。
思路:
a[j]−a[i]=a[k]−a[j]
可化为: 2×a[j]-a[k])=a]i]
- 枚举i时:
-
- 把i的放到map里
- 在枚举j,k的时
-
- 利用2×a[j]-a[k])=a]i]和
-
- map自带的"二分查询":mp.count()匹配
-
- 来把枚举i的时间复杂度O(n)降低到O(logn)。
unordered_map<>等价于无序(不排序)的map容器
代码:
- 来把枚举i的时间复杂度O(n)降低到O(logn)。
#include <bits/stdc++.h> using namespace std; #define ll long long int main() { int t; cin>>t; while(t--) { unordered_map<int,int> graph; int ans=0; int n; cin>>n; int a[n+1]; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int i=1;i<=n;i++) { graph[ a[i] ]++; for(int k=i+2;k<=n;k++) { int j=i+1; /*因为graph里面含有所有小于等于当前i的a[]数组的数据 *所有:只要j=i+1,就可以(假)遍历所有小于j的数组 */ if( graph.count(2*a[j]-a[k]) ) ans+=graph[ 2*a[j]-a[k] ]; } } cout<<ans<<endl; } return 0; }
J - Just the Last Digit Gym - 102411J
题意:
要求:有一张有向图, 只能从小的点跑向大的点,
input:点a跑到点b的可行方案数的个位数(a<b)
output:让任意两点间是否能直达.
思路:
点a到点b的方法只有:直达或者间接到达 (废话)
故方法:
- 枚举求出:所有间接可达的方案总数(具体看代码)
- %10后如果与给出的个位数相同, 则无法直达, 反之可以直达.
代码:
#include <bits/stdc++.h> typedef long long ll; using namespace std; const int MAXN = 510; char mp[MAXN][MAXN]; int res[MAXN][MAXN]; int main(void) { int n; cin >> n; for (int i = 1; i <= n; i++) { scanf("%s", mp[i] + 1); for (int j = 1; j <= n; ++j) { res[i][j] = mp[i][j] - '0'; } } for (int i = 1; i <= n - 1; ++i) { for (int j = i + 1; j <= n; ++j) { int temp = 0; //方案数 for (int k = i + 1; k <= j - 1; ++k) { temp += res[i][k] * res[k][j]; } res[i][j] = (temp + 1) % 10 == res[i][j]; } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { printf("%d", res[i][j]); } printf("\n"); } return 0; }
#include <bits/stdc++.h> using namespace std; #define int long long const int maxn=2e5+10; int n,k,a[100009],m; bool isok(int x) { int ans=0,num=0,j=1; /* *ans:多少个区间的第k大比mid还大 and 右端点 *num:统计有多少个数大于当前x *j:左端点 */ for(int i=1; i<=n; i++)//遍历A数组 { if( a[i]>=x ) { num++;//更新num } if( num==k )//说明包含当前区间的区间的第k大一定大于等于mid { ans+=(n-i)+1;//在 i+1 及其之后的区间大于x的点的个数都大于等于k个。 //右端点的取值 while( a[j]<x )//移动左端点 /* *如果左端点小于x,则对第k大无影响 */ { ans+=n-i+1; //在 i+1 及其之后的区间大于x的点的个数都大于等于k个。 j++; } num--; j++; } } if(ans>=m) return true;//如果当前x符合题意 else return false; } signed main() { int t; cin >> t; while( t-- ) { cin >>n>>k>>m; int l=1e9+1,r=0; for(int i=1; i<=n; i++) { cin >> a[i]; l = min(l,a[i]); r = max(r,a[i]); } int ans=0; while( r>=l ) { int mid =(l+r)/2; // cout <<mid <<endl; if( isok(mid) )//如果当前x符合题意 { l=mid+1;//二分缩短区间 ans=mid; } else { r=mid-1;//二分缩短区间 } } cout << ans <<endl; } }
本文作者:kingwzun
本文链接:https://www.cnblogs.com/kingwz/p/15307851.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步