题目大意:
给你n个图层,q次询问,每层图层的屏幕颜色由三个16进制数表示。每一次询问后输出最后出现在屏幕上的颜色。如果当前层上的m为1,则屏幕颜色变为当前层的颜色。如果m为2,则屏幕颜色变为上一次出现的屏幕颜色+该层屏幕颜色;
输入:
第一行包含单个整数T(1≤T≤10),即测试用例的数量。对于每个测试用例:
输入的第一行包含两个整数n和q(1≤n,q≤100000),表示层数和查询次数。
在接下来的n行中,第i行包含一个整数mi和一个6位十六进制大写字符串ci,用于描述第i层。
在接下来的q行中,第i行包含两个整数li和ri(1≤li≤ri≤n),描述第i个查询。
输出:
对于每个查询,打印包含6位16进制大写字符串的单行,表示最终显示的颜色。
这道题主要思路是前缀和,用三个数组分别记录每个颜色的十六进制数前缀和,用pos数组记录上一次m为1时的位置,每次查询比较pos[r]和l的最大值,各数组下标相减即可。(看的源码写的,有些地方解释的不够清楚请见谅)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int T,n,m,l,r,x,p[N],q[N],s[N],t[N],pos[N];//p、q、s三个数组用于储存三种颜色的前缀和,t数组存当前位置上的m值
inline int ask(int *s,int l,int r){
int x=pos[r],ret;if(x>l) l=x;//如果上一次m值为1的位置比l大,l=pos[r]
ret=s[r]-s[l-1];
return ret<255?ret:255;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%X",&t[i],&x);//16进制读入
p[i]=x&255;//255的二进制为1111111,x&255=x的二进制最后7位
x>>=8;//x右移8位,更新最后7位的值
q[i]=x&255;//同理
x>>=8;
s[i]=x;
p[i]+=p[i-1];
q[i]+=q[i-1];
s[i]+=s[i-1];
if(t[i]==1) pos[i]=i;else pos[i]=pos[i-1];
}
while(m--){
scanf("%d%d",&l,&r);
printf("%02X%02X%02X\n",ask(s,l,r),ask(q,l,r),ask(p,l,r));//十六进制输出
}
}
}