1002: Rikka with Cake
可以发现,答案=线段之间交点的个数+1。把x坐标离散化,把线段按起点的y坐标排序,先从下往上,求每个down的线段和多少个线段相交。再从上往下,求每个up的线段和多少个线段相交。
#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-(x)))
#define mid ((l+r)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
const int maxn = 1e5 + 50;
struct node{
int x, y;
int op;//0 L, 1 R, 2 U, 3 D
bool operator < (const node& a){
return y < a.y;
}
}e[maxn];
int lz[maxn*4];
int cc[maxn];
int num, n, m, q;
void build(int rt, int l, int r){
lz[rt] = 0;
if(l == r) return;
build(lson); build(rson);
}
void down(int rt){
lz[rt<<1] += lz[rt];
lz[rt<<1|1] += lz[rt];
lz[rt] = 0;
}
void update(int rt, int l, int r, int L, int R){
if(L <= l && r <= R){
lz[rt]++; return;
}
down(rt);
if(L <= mid) update(lson, L, R);
if(R > mid) update(rson, L, R);
}
int qry(int rt, int l, int r, int pos){
if(l == r){
return lz[rt];
}
down(rt);
if(pos <= mid) return qry(lson, pos);
else return qry(rson, pos);
}
void init()
{
num = 0;
scanf("%d%d%d", &n, &m, &q);
cc[++num] = 0; cc[++num] = m;
for(int i = 0; i < q; ++i){
char cmd[5];
scanf("%d%d", &e[i].x, &e[i].y);
scanf("%s", cmd);
cc[++num] = e[i].x;
if(cmd[0] == 'L') e[i].op = 0;
else if(cmd[0] == 'R') e[i].op = 1;
else if(cmd[0] == 'U') e[i].op = 2;
else e[i].op = 3;
}
sort(cc+1,cc+1+num);
num = unique(cc+1,cc+1+num)-cc-1;//x的离散化
}
void sol(){
sort(e, e+q);//按y从小到大
ll ans = 1;
build(1, 1, num);
for(int i = 0; i < q; ++i){
if(e[i].op == 0){
int r = lower_bound(cc+1,cc+1+num, e[i].x) - cc;
update(1, 1, num, 1, r);
}
else if(e[i].op == 1){
int l = lower_bound(cc+1,cc+1+num, e[i].x) - cc;
update(1, 1, num, l, num);
}
else if(e[i].op == 3){
int pos = lower_bound(cc+1,cc+1+num, e[i].x) - cc;
int t = qry(1, 1 , num, pos);
ans = ans + t;
}
}
build(1, 1, num);
for(int i = q-1; i >= 0; --i){
if(e[i].op == 0){
int r = lower_bound(cc+1,cc+1+num, e[i].x) - cc;
update(1, 1, num, 1, r);
}
else if(e[i].op == 1){
int l = lower_bound(cc+1,cc+1+num, e[i].x) - cc;
update(1, 1, num, l, num);
}
else if(e[i].op == 2){
int pos = lower_bound(cc+1,cc+1+num, e[i].x) - cc;
int t = qry(1, 1 , num, pos);
ans = ans + t;
}
}
cout<<ans<<endl;
}
int main()
{
int T;cin>>T;
while(T--){
init();sol();
}
}
1005: Rikka with Game
第一个人如果想让字典序变小,一定会找一个z使得它变成a,同时这个z前面必须全是y。如果不全是y,那么第一个人把z变成a之后,第二个人可以让前面的字母变大,且第一个人无法使之变小。
如果没有满足条件的z,第一个人就不能让字典序更小,直接结束是最优选择。
如果有满足条件的z,第一个人让它变成a之后,第二个人一定会让它变成b,这时第一个人结束游戏是最优选择(否则就算第一个人把后面某个z变成a,第二个人把这个b变成c会让字典序更大)
#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn = 200;
char s[maxn];
int main()
{
int T;cin>>T;
while(T--){
scanf("%s", s);
int n = strlen(s);
int idx = 0;
while(idx < n && s[idx] >= 'y'){
if(s[idx] == 'z') break;
idx++;
}
if(s[idx] == 'z') s[idx] = 'b';
printf("%s\n",s);
}
}
1006:Rikka with Coin
容易知道,对于答案来说:
1最多有1个(如果需要两个1,那换成一个1,一个2显然更好)
2最多有4个,5最多有1个(与1同理)
那么枚举1,2,5的个数,再看对于每个套餐来说,最少需要多少个10.
#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int inf = 0x3f3f3f3f;
int dp[25];
int w[150];
int n;
int check(int x, int y, int z)//1, 2, 5
{
memset(dp, 0x3f, sizeof dp);
dp[0] = 0;
for(int i = 0; i < x; ++i){
for(int j = 20; j >= 1; --j){
dp[j] = min(dp[j], dp[j-1]+1);
}
}
for(int i = 0; i < y; ++i){
for(int j = 20; j >= 2; --j){
dp[j] = min(dp[j], dp[j-2] + 1);
}
}
for(int i = 0; i < z; ++i){
for(int j = 20; j >= 5; --j){
dp[j] = min(dp[j], dp[j-5]+1);
}
}//dp求得1,2,5个数为x,y,z时可以凑的数字
int res = 0;//需要的额外的10的个数
for(int i = 0; i < n; ++i){
int t = w[i]%10;
int fnd = 0;
int temp = inf;
if(dp[t] != inf){
temp = min(w[i]/10, temp);
fnd = 1;
}
t = t+10;
if((w[i] >= t) && dp[t] != inf){
fnd = 1;
temp = min(temp, (w[i]-t)/10);
}
if(!fnd) return -1;
res = max(res, temp);
}
return res;
}
int main()
{
int T;cin>>T;
while(T--){
scanf("%d", &n);
int ok = 1;
for(int i = 0; i < n; ++i){
scanf("%d", &w[i]);
if(w[i]%10 != 0) ok = 0;
w[i]/=10;
}
if(!ok){
printf("-1\n"); continue;
}
int ans = inf;
for(int i = 0; i < 2; ++i){//1最多1个
for(int j = 0; j < 5; ++j){//2最多4个
for(int k = 0; k < 2; ++k){//5最多1个
int u = check(i, j ,k);
if(u != -1) ans = min(ans, i+j+k+u);
}
}
}
printf("%d\n", ans);
}
}
/*
1
6
1040 1050 1060 1100 150 200
*/
/*
1
6
40 50 60 100 150 200
*/