http://118.190.20.162/home.page
小明种苹果
题意:n棵树,m次操疏果操作。(a_{i0}表示第i颗初始苹果数量,a_{ij}(1<=j<=m)表示第i棵树第j次疏果,其绝对值为疏果数量)。
求疏果完毕后树上苹果所剩总数,疏果数最多的编号如果存在相等疏果数输出编号较小的苹果树,该树疏果数量。
解法:第一问:苹果所剩总数只需将n*m+1内矩阵的数全部相加
第二问和第三问:创建结构体数组成员为疏果数量和该棵树编号,统计相关信息进行,以疏果数量为第一关键字标号为第二关键字排序。排序完后第一数组元素即为答案。
const int maxn = 1e3+9;
struct node{
int num , id ;//第i棵树疏果数和编号
}a[maxn];
bool cmp(node a , node b){//以疏果数为第一关键字,编号为第二关键字排序
if(a.num != b.num) return a.num > b.num;
return a.id < b.id;
}
void solve(){
int n , m , sum = 0 ;
scanf("%lld%lld" , &n , &m);
rep(i , 1 , n){
int x ;
scanf("%lld" , &x);
sum += x ;
a[i].num = 0;
a[i].id = i ;
rep(j , 1 , m){
scanf("%lld" , &x);
a[i].num -= x ;
sum += x ;
}
}
sort(a+1 , a+1+n , cmp);
cout << sum << " " << a[1].id << " " << a[1].num << endl;
}
小明种苹果(续)
题意:n棵树,每棵树有(m_i)次操作 , 每次操作如果为正数为记录此时苹果数,负数为疏果数。第一次操作一定为正数,操作过程中不会出现苹果树为负数。所有苹果树为首尾相连的环形。
问:
1、所剩苹果树总数
2、有几棵树的苹果存在非疏果脱离苹果树数量
3、有几个三个相邻的苹果树存在第二个问题的情况
解法:见码
int num[maxn];//记录树上苹果数量
void solve(){
int n , sum = 0 , ans = 0;
scanf("%lld" , &n);
set<int>s;
rep(i , 1, n){
int m ;
scanf("%lld" , &m);
scanf("%lld" , &num[i]);//初始值
rep(j , 2 , m){
int x ;
scanf("%lld" , &x);
if(x < 0){
num[i] += x ;//疏果后
}else if(x > 0){
if(num[i] != x){//如果不等说明出现自动脱离的情况
s.insert(i);
num[i] = x ;
}
}
}
sum += num[i];
}
if(size(s) < 3){
cout << sum << " " << size(s) << " " << 0 << endl;
return ;
}
for(auto i : s){//判断相邻三个自动脱离数量
if(i == 1){
if(s.count(n) && s.count(2)){
ans++;
}
}else if(i == n){
if(s.count(1) && s.count(n-1)){
ans++;
}
}else{
if(s.count(i-1) && s.count(i+1)){
ans++;
}
}
}
cout << sum << " " << size(s) << " " << ans << endl;
}
字符画
题意:给出大小为(n*m)的图片,每一小格为一个像素,一个像素由三个值(R,G,B)构成,值由0-255的16进制表示,现在需要将这张图片划分成(q*p)大小的像素块,求像素块的值为平均值。
如果当前像素块的颜色与前一个像素块的颜色不同,如果为背景色则直接输出转义序列ESC[0m.否则输出更改颜色的转义序列ESC[48;2;R;G;Bm
如果与前一像素块颜色相同则不需要更改颜色。
输入:输入m,n,p,q.接下来(n*m)行分别表示一个像素的16进制的表示,如果为#a,则需转化为#aaaaaa.如果为#abc,转为#aabbcc。
输出:全部输出位16进制序列,有(m*n/p*q)个空格(即每个像素块后跟一个空格),(n/q)有个回车(即每一行的像素块结束输出一个回车)。注意空格与回车都为16进制的转移字符。
考点:十六进制转十进制、数字拆分、十进制转16进制。
const int maxn = 2e3+9;
int c[maxn][maxn][3];//像素点
string s ;
int R , r , G , g , B , b ;
int turn10(char a , char b){//十六进制转为10进制
return (isalpha(a)?(a-'a'+10):(a-'0'))*16 + (isalpha(b)?(b-'a'+10):(b-'0'));
}
void outchar(int a){//十进制转为十六进制
printf("\x%02X" , a);
}
void outstr(string s){//字符串转十六进制
for(auto i : s){
outchar(i);
}
}
void outnum(int i){//数字拆分,转十六进制
vector<int>v;
if(i==0)v.pb(i);
while(i>0) v.pb(i%10) , i/=10;
for(i = size(v)-1 ; i >= 0 ; i--)outchar('0'+v[i]);
}
void solve(){
int n , m , p , q , num ;
cin >> m >> n >> p >> q;
num = p*q;
rep(i , 0 , n-1){
rep(j , 0 , m -1){
cin >> s;
if(size(s) == 2){//将#a格式转换为#aaaaaa
s += string(5 , s[1]);
}else if(size(s) == 4){//将#abc转为#aabbcc
s = "#" + string(2 , s[1]) + string(2 , s[2]) + string(2 , s[3]);
}
rep(k , 0 , 2){
c[i][j][k] = turn10(s[k*2+1] , s[k*2+2]);//两两为一组16进制求10进制
}
}
}
for(int i = 0 ; i < n ; i += q){
for(int j = 0 ; j < m ; j += p){
R = G = B = 0 ;
for(int k = i ; k < i + q ; k++){
for(int l = j ; l < j + p ; l++){
R += c[k][l][0] , G += c[k][l][1] , B += c[k][l][2];//当前像素块的像素和
}
}
R /= num , G /= num , B /= num ;//像素块的平均值
if(!(R==r&&G==g&&B==b)){//与前一个像素块颜色不同
if(R==0&&G==0&&B==0){//为默认颜色
outstr(string(1,char(27)) + "[0m");//重置转义序列
}else{//更改颜色
outstr(string(1,char(27)) + "[48;2;") , outnum(R),
outchar(';'),outnum(G),outchar(';'),outnum(B),outchar('m');
}
r = R , g = G , b = B ;//记录前一像素块颜色
}
outchar(' ');//mn/pq个空格
}
if(R!=0||G!=0||B!=0) outstr(string(1,char(27))+"[0m");//行末判断是否为默认颜色
r = g = b = 0 ;//转为默认色
outchar('
');//n/q个换行
}
}
推荐系统
题意:m种商品编号0-m-1,初始每类有n件商品,给出编号和分数,任意时刻,同一类商品不存在标号相同的两个商品。共有q次操作,有三种操作:
1、增加新商品
2、删除某一商品
3、一共选出商品数量不超过K个,每一种类选择不超过(k_i)个商品。输出在满足条件下,m类分大的编号每一类占一行,不存在输出-1。
解法:一开始写用了重载运算符优先队列,但是因为每次询问都是对后面询问产生影响的,就不好保存数据 , 代码写的很丑。
之后看了下网上的代码,发现使用重载运算符的set(第一次做到重载set的运算符,所以没有想到用set去存数据)。
- 增加操作:直接使用set插入。
- 删除操作:因为只给出了商品的种类和编号没有给出分数,所以不好直接set删除数据,所以选择使用二维map将该商品标记(当然可以也去记录商品分数同样需要二维map),使用map只能拿80分,用unordered——map才能拿满分。
因为map时间复杂度大一些为O(logn),而unordered——map因为不会对数据排序所以时间复杂度低为O(1). - 直接遍历set数据,对于标记的直接过掉。
数据范围:m(<=50),n(<=3e4),id(<=1e9),q(<=1e5),ask3(<=100)
const int maxn = 59;
int k[maxn];
struct node{
int ty , id , sc;
bool operator < (const node a)const {
if(sc != a.sc) return sc > a.sc;//商品分数为第一关键字
if(ty != a.ty) return ty < a.ty;//类型为第二关键字
return id < a.id;//标号为第三关键字
}
node(int _ty , int _id , int _sc){
ty = _ty , id = _id , sc = _sc;
}
node(){}
};
unordered_map<int , int>vis[maxn];//标记删除商品
void solve(){
set<node>s;
int m , n ;
scanf("%lld%lld" , &m , &n);
rep(i , 1 , n){
int x , y ;
scanf("%lld%lld" , &x , &y);
rep(j , 0 , m-1){//每一种类都插入标号为x分数为y的商品
s.insert(node(j , x , y));
}
}
int q ;
scanf("%lld" , &q);//q次操作
while(q--){
int t , x , y , z ;
scanf("%lld" , &t);
if(t == 1){
scanf("%lld%lld%lld" , &x , &y , &z);
s.insert(node(x , y , z));//新增商品
}else if(t == 2){
scanf("%lld%lld" , &x , &y);
vis[x][y] = 1 ;//标记删除商品
}else{
int K ;
scanf("%lld" , &K);//总共选择不超过K个商品
vector<int>v[maxn];
rep(i , 0 , m-1){
scanf("%lld" , &k[i]);//每一种商品选不超过ki个商品
}
int ans = 0 ;
for(auto i : s){
if(ans >= K) break;
if(vis[i.ty][i.id]) continue;
if(k[i.ty]){
v[i.ty].pb(i.id);
k[i.ty]--;
ans++;
}
}
rep(i , 0 , m-1){
if(!size(v[i])){
printf("-1
");
continue;
}
int flag = 0;
for(auto j : v[i]){
if(!flag) printf("%lld" , j) , flag = 1;
else printf(" %lld" , j);
}
printf("
");
}
}
}
}