0
点赞
收藏
分享

微信扫一扫

2021“MINIEYE杯”中国大学生算法设计超级联赛(3) - 1007(Photoshop Layers)

​​原题跳转​​

​前缀和思想​

​开一个数组pre记录当前位置之前包括(当前位置)距离最近的1的位置​​​​开一个sum数组记录从当前位置之前(包括当前位置)距离最近的1的位置到当前位置的前缀和​​​​即sum[i] 记录 pre[i] ⇒ i 区间的前缀和​

​求l, r之间的和时, 如果l, r区间有1(即pre[r] >= l), 则输出从最后一个1的位置到r的和,及sum[r]的值​​​​如果l, r区间之间没有1(即pre[r] < l),则根据前缀和思想输出:sum[r] - sum[l - 1]的值​

#include<iostream>
using namespace std;

typedef long long ll;

// pre数组记录上一个1的位置
int t, n, q, pre[100005];
char chs[10];

// 前缀和, 从上一个1到当前位置的前缀和
ll sum[100005][3];

int tonum(char &c){

if('0' <= c && c <= '9'){
return c - '0';
}
return c - 'A' + 10;
}

// 16进制字符转10进制数字
int trans(char &c1, char &c2){

int t1 = tonum(c1);
int t2 = tonum(c2);

return t1 * 16 + t2;
}

char tochar(int &x){
if(x > 9) return 'A' + x - 10;
return '0' + x;
}

// 10进制数字转16进制
void toCh(int num){
int x1 = num % 16;
int x2 = num / 16 % 16;

char c1 = tochar(x1);
char c2 = tochar(x2);

printf("%c%c", c2, c1);
}

int main(){


scanf("%d", &t);

while (t--){

scanf("%d%d", &n, &q);

// d代表当前输入的数字, p为上一个1的位置, 碰到d=1之后更新
int d, p = 1, R, G, B;
for (int i = 1; i <= n; ++i) {

scanf("%d", &d);
scanf("%s", chs);

// 拆分到为3个十进制数存储
R = trans(chs[0], chs[1]);
G = trans(chs[2], chs[3]);
B = trans(chs[4], chs[5]);

if(d==1){
// 更新1的位置
p = i;

// 当d=1时,前缀和为自己
sum[i][0] = R;
sum[i][1] = G;
sum[i][2] = B;
}else{

// 前缀和: 从上一个1的位置加到当前位置
sum[i][0] = sum[i-1][0] + R;
sum[i][1] = sum[i-1][1] + G;
sum[i][2] = sum[i-1][2] + B;
}

// 左边(包括当前位置)距离当前位置最近的1的位置
pre[i] = p;
}


int l, r;

for (int i = 1; i <= q; ++i) {
scanf("%d%d", &l, &r);
// 如果l ==> r之间有1, 前缀和即结果
if(l <= pre[r]){
R = sum[r][0];
G = sum[r][1];
B = sum[r][2];
}else{
// 如果 l-->r之间没有1, 则为sum[r] - sum[l-1] // 前缀和思想
R = sum[r][0] - sum[l - 1][0];
G = sum[r][1] - sum[l - 1][1];
B = sum[r][2] - sum[l - 1][2];
}

// 在255和当前值之间取最小值
R = min(255, R);
G = min(255, G);
B = min(255, B);

// 转16进制并输出
toCh(R);
toCh(G);
toCh(B);

printf("\n");
}
}
return 0;
}


举报

相关推荐

0 条评论