A
思路:这题我感觉写复杂了。
我的思路是贪心:尽可能让所有的战机拿到贡献,并且在当前这辆战机在可以拿的贡献中拿最大的。
那么,先对自己的战机和敌人的战机按照防御值升序。
然后枚举自己的所有战机,因为敌人的战机已经排序了,我们二分出最后一个小于当前这辆战机的位置,然后在区间[1,index]找最大值。
这就是一个区间最大值的问题了,可以用线段树来维护一下就行了。
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<map> #include<queue> using namespace std; const int maxn = 2e6 + 10; typedef long long int ll; struct node{ ll d,v; }s[maxn]; ll a[maxn]; bool cmp(ll x,ll y){ return x < y; } bool cmp2(node x,node y){ return x.d < y.d; } #define lson (rt * 2) #define rson (rt * 2 + 1) int pos; ll m[maxn]; void build(int l,int r,int rt){ if(l == r){ m[rt] = s[pos ++].v; return ; } int mid = l + r >> 1; build(l,mid,lson); build(mid + 1,r,rson); m[rt] = max(m[lson],m[rson]); } ll query(int l,int r,int ql,int qr,int rt){ if(l >= ql && r <= qr){ return m[rt]; } int mid = l + r >> 1; ll res = 0; if(ql <= mid)res = max(res,query(l,mid,ql,qr,lson)); if(qr > mid)res = max(res,query(mid + 1,r,ql,qr,rson)); return res; } void solved(){ int n,m;scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++)scanf("%lld",&a[i]); for(int i = 1; i <= m; i++)scanf("%lld",&s[i].d); for(int i = 1; i <= m; i++)scanf("%lld",&s[i].v); sort(a + 1,a + 1 + n,cmp); sort(s + 1,s + 1 + m,cmp2); pos = 1; build(1,m,1); ll ans = 0; for(int i = 1; i <= n; i++){ int l = 1,r = m; int index = -1; while(l <= r){ int mid = l + r >> 1; if(s[mid].d >= a[i]){ r = mid - 1; }else{ index = mid; l = mid + 1; } } if(index == -1)continue; ans += query(1,m,1,index,1); } printf("%lld\n",ans); } int main(){ solved(); return 0; }
E
思路:
先求出你和你朋友有多少个相同的题,那么你这个时候能对min(same,n - k)个,然后他错了几道题就意味着你对了几道题min(k,n - same)。
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<map> using namespace std; const int maxn = 2e5 + 10; typedef long long int ll; bool you[maxn],f[maxn]; void solved(){ int n,k;cin>>n>>k; for(int i = 1; i <= n; i++)cin>>you[i]; for(int i = 1; i <= n; i++)cin>>f[i]; int same = 0; for(int i = 1; i <= n; i++){ if(you[i] == f[i])same++; } cout<<min(n - k,same) + min(k,n - same) <<endl; } int main(){ solved(); return 0; }
G
思路:
随便玩几个样例就发现规律了。
n = 1
0
1
n = 2
0 [0]
0 [1]
1 [1]
n = 3
0 [0 0]
0 [0 1]
0 [1 1]
1 [1 1]
dp[i][0] = dp[i - 1][0] + dp[i - 1][1]
dp[i][1] = 1
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<map> using namespace std; const int maxn = 2e5 + 10; typedef long long int ll; ll mod = 998244353 ; ll dp[maxn][2]; void solved(){ int n;cin>>n; dp[1][0] = dp[1][1] = 1; for(int i = 2; i <= n; i++){ dp[i][0] = (dp[i][0] + ((dp[i - 1][0] + dp[i - 1][1]) % mod)) % mod; dp[i][1] += 1; } cout<<(dp[n][0] + dp[n][1]) % mod <<endl; } int main(){ solved(); return 0; }
H
思路:计算两个圆心距离,然后把外离与内含的情况去掉,其它均可。
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<cmath> #include<map> using namespace std; const int maxn = 2e5 + 10; typedef long long int ll; void solved(){ ll x1,y1,r1,x2,y2,r2; scanf("%lld%lld%lld%lld%lld%lld",&x1,&y1,&r1,&x2,&y2,&r2); double d = sqrt(double((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))); if(d > r1 + r2){ cout<<"NO"<<endl;return ; } if(d < abs(r1 - r2)){ cout<<"NO"<<endl;return ; } cout<<"YES"<<endl; } int main(){ int t;cin>>t; while(t--) solved(); return 0; }
D
思路:
可以知道m次是固定的就非叶子节点的数,并且我们知道,每次大园林剪或者小园林剪都会把根节点的值覆盖掉,那么我们可以知道,根节点最后的生命力的值一定是来自叶子节点,即非叶子节点的值其实是无用的。
那么我们只需要那大最大的叶子节点的贡献即是答案,要拿到某个叶子节点的值需要满足dep[u] <= 大林园剪的次数(一路大林园剪上去)
大园林剪的次数 = n - 叶子节点 对 2 向上取整。
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<map> using namespace std; const int maxn = 2e5 + 10; typedef long long int ll; ll G[maxn][2]; ll w[maxn]; int dep[maxn]; bool vis[maxn]; void dfs(int u,int de){ if(u == 0)return ; dep[u] = de + 1; dfs(G[u][0],de + 1); dfs(G[u][1],de + 1); } void solved(){ int n;scanf("%d",&n); int cnt = 0; for(int i = 1; i <= n; i++){ int l,r;scanf("%d%d",&l,&r); G[i][0] = l;G[i][1] = r; if(l == r && l == 0)cnt++,vis[i] = true; } dfs(1,-1); int k = n - cnt;k = (k + 1) / 2; ll ans = 0; for(int i = 1; i <= n; i++){ scanf("%lld",&w[i]); if(vis[i] && dep[i] <= k){ ans = max(ans,w[i]); } } cout<<ans<<endl; } int main(){ solved(); return 0; }