• P3939 数颜色


    P3939 数颜色

    题意: 给出一个序列, 有两个操作
    1.输出 ([l,r]) 有几个为 (c) 的数
    2.交换 (x)(x + 1) 的数


    错误日志: 1.写错了一个数组 2.二分 (vector) 手写了(下次使用 (vector) 尽量避免手写, 需要熟练运用 (lower\_bound)(upper\_bound)


    Solution

    首先考虑数据结构, 无奈不会
    然后仔细分析题意(其实这是第一步应该做的!!!!警示!), 发现修改操作一次只是要交换相邻两数
    然后分类讨论:
    1.相邻两数值相同: 这时交换与不交换等价
    2.相邻两数值不同: (重点分析的是这个)
    对于一种颜色, 我们先建立一个排名
    很显然因为交换的两数颜色不同, 所以交换这两数不会改变 交换颜色的 原排名
    所以我们建立一个 (vector<int>col)(col[i][j]) 表示第 (i) 种颜色 排名第 (j) 的坐标, 显然此序列单调递增, 且当 (j)(1-col[i][j]) 的颜色数
    故查询时直接按坐标二分查找, 类似前缀和地处理出有几种颜色
    因为修改不会改变排名, 进而不会改变单调性, 所以直接交换位置信息即可

    在读入时加入一个指针的概念可以将修改的复杂度优化到 (O(1))
    故复杂度上限位 (O(log n))

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    typedef long long LL;
    using namespace std;
    int RD(){
        int out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const int maxn = 300019;
    int num, na;
    int ori[maxn], pos[maxn];
    vector<int>col[maxn];//col[i][j]表示第i个颜色出现第j个的坐标
    int main(){
    	num = RD();na = RD();
    	for(int i = 1;i <= num;i++)col[i].push_back(0);
    	for(int i = 1;i <= num;i++){
    		ori[i] = RD();
    		col[ori[i]].push_back(i);
    		pos[i] = col[ori[i]].size() - 1;//访问指针
    		}
    	for(int i = 1;i <= na;i++){
    		int cmd = RD();
    		if(cmd == 1){
    			int l = RD(), r = RD(), c = RD();//bound查找返回下标
    			int p1 = lower_bound(col[c].begin(), col[c].end(), l) - col[c].begin() - 1;
    			//1 - (l - 1)的个数
    			int p2 = upper_bound(col[c].begin(), col[c].end(), r) - col[c].begin() - 1;
    			printf("%d
    ", p2 - p1);
    			}
    		else{
    			int x = RD();
    			if(ori[x] == ori[x + 1])continue;
    			int c1 = ori[x], c2 = ori[x + 1];
    			int p1 = pos[x], p2 = pos[x + 1];
    			swap(col[c1][p1], col[c2][p2]);
    			swap(pos[x], pos[x + 1]);
    			swap(ori[x], ori[x + 1]);
    			}
    		}
    	return 0;
    	}
    
  • 相关阅读:
    openssl生成公钥私钥对 加解密
    boost replace_if replace_all_regex_copy用法
    PS 图像滤镜— — USM 锐化
    使用boost库生成 随机数 随机字符串
    改动Android设备信息,如改动手机型号为iPhone7黄金土豪版!
    验证(Verification)与确认(Validation)的差别
    Spring-SpringMVC-Hibernate整合
    全面整理的C++面试题
    Metropolis Hasting算法
    捕捉到来自宇宙深空的神奇X-射线信号
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9500928.html
Copyright © 2020-2023  润新知