A. Level Statistics
题意:一个游戏,给你多个有序列的挑战的次数x和赢的次数y,求这样的序列是否合理,主要难点就在读题上,英语不好真的伤。
思路:首先x[i]>=y[i],其次x[i+1]>=x[i]&&y[i+1]>=y[i],然后x[i+1]-x[i]>=y[i+1]-y[i]满足这些条件就是合法的序列,具体看代码实现。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <deque>
#include <cstring>
#include <algorithm>
using namespace std;
#define sc(x) scanf("%lf", &x)
const int mod = 1e9+7;
typedef long long ll;
const int M = 1010;
struct node{
int x, y;
}a[M];
bool cmp(node x, node y){
return x.x<y.x;
}
int main(){
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int flag = 1;
for(int i = 0; i < n; i++){
cin>>a[i].x>>a[i].y;
if(a[i].x<a[i].y) flag = 0;
}
for(int i = 1; i < n; i++){
if(a[i-1].x>a[i].x||a[i-1].y>a[i].y){
flag = 0;break;
}else if(a[i].y-a[i-1].y>a[i].x-a[i-1].x){
flag = 0; break;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
B. Middle Class
题意:现在你知道n个人的财富值,然后给你一个衡量富人的标准值,即第i个人的财富值大于等于这个财富值他就算富人,现在你可以对任意两人进行财富的平均分配,可进行多次,求最多可以有多少个富人。
思路:这个思路比较简单就直接sort一下,然后设富人的个数为ans个,当前拥有的总财富sum>=ans*s即可以满足当前ans个都可以变为富人,当这个等式不成立的时候即表明富人已经达到了最大的个数,注意点long long。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstring>
#include <vector>
using namespace std;
#define maxn 100010
const int M = 1e5+10;
typedef long long ll;
ll a[M];
int main(){
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
ll n, s;
cin>>n>>s;
for(int i = 0; i < n; i++){
cin>>a[i];
}
sort(a, a+n);
ll ans = 0;
ll sum = 0;
for(int i = n-1; i >= 0; i--){
sum += a[i];
if(sum >= s*(ans+1)){
ans++;
}else break;
}
printf("%lld\n", ans);
}
return 0;
}
C. Circle of Monsters
题意:n个怪兽围成一个圈,然后给你第i个怪兽的血量a[i]和该怪兽死后所产生的爆炸伤害b[i],产生的爆炸伤害是对该怪兽的下一个,如果i=n,则是对第一个产生b[n]的爆炸伤害,同时你可以打出子弹对怪兽造成伤害,每发子弹对怪兽造成一点的伤害,求你最少打出的子弹数。
思路:首先可以假设每个怪兽都直接爆炸,然后求出剩下怪兽的血量进行求和sum,因为首先你要打爆一个怪兽,使其爆炸,也就意味着你肯定有一个爆炸所带来的伤害要空掉,所以对所有的怪兽进行遍历求打死该怪兽所需要的子弹数减去它被它前一个怪兽爆炸后还剩余的血量,即max(0, a[i]-b[i-1])。具体看代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define INF 1ll<<60
const int maxn = 3e5+10;
ll a[maxn], b[maxn];
int main(){
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
ll n;
cin>>n;
rep(i, 1, n+1){
cin>>a[i]>>b[i];
}
b[0] = b[n]; //这里是为了方便计算
ll sum = 0;
rep(i, 1, n+1){
if(a[i] > b[i-1])
sum += a[i]-b[i-1];
}
ll ans = INF;
rep(i, 1, n+1){
ll tmp;
if(a[i]>b[i-1]) tmp = a[i]-b[i-1];
else tmp = 0;
if(ans > a[i]+tmp){
ans = a[i]+tmp;
}
}
cout<<ans+sum<<endl;
}
return 0;
}
D. Minimum Euler Cycle
题意:欧拉回路,如果n为4的话,为1 2 1 3 1 4 2 3 2 4 3 4 1,可以看成是一种规律,也可以画图来分析出为了构成欧拉回路,且要字典序最小所以是要以n为类似的周转站,依次进行下去,最后回到1。
思路:分析规律可以看出 1 2 1 3 1 4 || 2 3 2 4 || 3 4 || 1,假设每个部分的奇位数位num,则可以得到每个部分数的个数为(n-num)2,然后要输出的是【l,r】内的,可以用一个数组s【i】来存储该位之前(包含第i位)拥有多少个数字(i表示的就是前面的num)所以可以知道 s[i]=s[i-1]+2(n-i),之后用二分来得到第i位位于的区间,如果是奇位的话输出该位位于的区间pos,如果是偶位的话输出pos+(i-s[pos-1])/2。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n-1; i >= a; i--)
#define INF 1ll<<60
const int maxn = 1e5+10;
ll s[maxn];
int main(){
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
ll n, l, r;
cin>>n>>l>>r;
rep(i, 1, n){
s[i] = s[i-1]+(ll)2*(n-i);
}
for(ll i = l; i <= r; i++){
if(i>s[n-1]) {printf("1 ");break;} //如果i大于s[i-1]表示该位是从n返回1,所以输出1
int pos = lower_bound(s+1, s+n, i)-s;
int num = i - s[pos-1];
if(num%2==1) printf("%d ", pos);
else printf("%d ", num/2+pos);
}
printf("\n");
}
return 0;
}