AtCoder Beginner Contest 128 DEF
https://atcoder.jp/contests/abc128
D题
题意:
v数组长度是n,代表有n个珠宝,可以进行k次操作;
每次操作,可以选择
1 从左边拿一个到手里
2 或者从右边拿一个手里
3 或者从手里放回一个到左边
4 或者从手里放回一个到右边
问最后手里所拥有珠宝价值总和最大
思路:
还以为是什么复杂的dp,但其实暴力就可以。
按照贡献来想
两重暴力循环,从左边拿几个,从右边拿几个,如果k次操作有剩,则将手里小于0的珠宝放回去。
int t,n,m;
int a[N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
ll res = 0;
for(int i=0;i<=n;i++){
for(int j=0;i+j<=n;j++){
if(i + j > m) continue;
int k = m - i - j;
ll tmp = 0;
priority_queue<int,vector<int>,greater<int>> q;
for(int op=1;op<=i;op++) q.push(a[op]),tmp+=a[op];
for(int op=n;op>n-j;op--) q.push(a[op]),tmp+=a[op];
while(q.size() && q.top() < 0 && k>0){
tmp -= q.top();
k--;
q.pop();
}
res = max(res,tmp);
}
}
printf("%lld\n", res);
return 0;
}
E题 贪心,stl,思维
题意:
数轴上,n个障碍物,
第i个障碍物,在[Si,Ti)这个时间段存在于数轴的Xi点上
Q个人,一开始都在数轴的0点上
Di代表这个人在Di秒向数轴正半轴出发,速度1秒1格
问每个人最远可以走到哪,如果可以走无限远则输出-1。
思路:
因为速度是1秒1格,所以时间和距离有相对关系。
每个障碍物都有对应在0点上的[Si,Ti)即从0点在这个时间段出发正好和障碍物时间段对应。
用set存每个人的出发时间。
按照障碍物的Xi,排序,因为距离近的先碰到。
每次lower_bound查找在这个时间段的人,然后标记被这个障碍物阻挡。
每次标记完只会,从set中erase掉。
int t,n,m,q;
struct node{
int s,t,x;
bool operator<(const node &no)const{
return x < no.x;
}
}bo[N];
int res[N];
map<int,int> pos;
set<int> se;
vector<int> tmp;
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
bo[i].s = max(a-c,0);
bo[i].t = max(b-c,0);
bo[i].x = c;
}
sort(bo+1,bo+1+n);
for(int i=1;i<=q;i++){
int x;
scanf("%d",&x);
se.insert(x);
pos[x] = i;
}
memset(res,-1,sizeof res);
for(int i=1;i<=n;i++){
auto l = se.lower_bound(bo[i].s);
auto r = se.lower_bound(bo[i].t);
for(auto j = l ; j != r; j++){
res[pos[*j]] = bo[i].x;
tmp.push_back(*j);
}
for(auto t : tmp) se.erase(t);
tmp.clear();
}
for(int i=1;i<=q;i++){
printf("%d\n", res[i]);
}
return 0;
}
F题
转载自:https://www.cnblogs.com/Dup4/p/10929996.html
太妙了,具体的解释,注释里解释下。
ll t,n,m;
ll s[N];
int vis[N];
int main(){
scanf("%lld",&n);
for(int i=0;i<n;i++) scanf("%lld",&s[i]);
ll res = 0;
//C = A - B 如果A <= B ,就会跳到<=0,所以从1开始
for(int C = 1;C <= n;C ++){
ll tmp = 0;
for(int k=1;1ll * k * C < n;k++){// k * C < n
ll a = k * C;//增加的第一个点
ll b = n - 1 - k * C;//增加的第二个点
//由公式A+KC = N - 1反推A,由C = A - B反推B
ll A = b,B = b - C;
if(A <= 0 || B <= 0) break;//题目说了A,B是正整数
//如果跳出范围或者重复了
if(a < 0 || a >= n || b < 0 || b >= n || a == b) break;
//如果在当前这层重复了。(这样就不用每次memset)
if(vis[a] == C || vis[a] == C){
break;
}
vis[a] = C;
vis[b] = C;
tmp += s[a];
tmp += s[b];
res = max(res,tmp);
}
}
printf("%lld\n", res);
return 0;
}