Gym 100342F Move to Front

用树状数组动态和查询修改排名。

树状数组可以很方便地查询前缀和,那么可以利用这一特点,记录一个点在树状数组里最后一次出现的位置,

查询出这个位置,就可以知道这个点的排名了。更改这个点的排名的时候只要把原来位置修改成0,然后在新的位置加上1就行了。

把询问离线,数据范围比较大,先用快排+去重离散(用map也可,就是慢了一点),

很久以前看的了,今天第一次实现

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5, N = maxn*2-1;

int a[maxn],q[maxn],C[N+1],sz,pos[maxn];

#define lowbit(x) ((x)&-(x))

void add(int x,int d)
{
    while(x<N){
        C[x] += d; x += lowbit(x);
    }
}

int sum(int x)
{
    int ret = 0;
    while(x>0){
        ret += C[x]; x -= lowbit(x);
    }
    return ret;
}

int b_search(int val,int *A = a,int l = 0,int r = sz)
{
    int m;
    while(l<r){
        m = (l+r)>>1;
        if(val>A[m]) l = m+1;
        else if(val<A[m]) r = m;
        else return m;
    }
    return -1;
}

int main()
{
    freopen("mtf.in","r",stdin);
    freopen("mtf.out","w",stdout);
    int n; cin>>n;
    for(int i = 0; i < n; i++) scanf("%d",a+i),q[i]=a[i];
    sort(a,a+n);
    sz = unique(a,a+n)-a;
    for(int i = 0; i < sz; i++){
        add(pos[i] = maxn+i,1);
    }
    int cur = maxn-1;
    for(int i = 0; i < n; i++){
        int x = b_search(q[i]), ans; //cout<<x<<endl;
        if(pos[x] == maxn+x) ans = sum(pos[x]) - x-1 + q[i];
        else ans = sum(pos[x]);
        printf("%d%c",ans,i==n-1?‘\n‘:‘ ‘);
        add(pos[x],-1);
        add(pos[x] = cur--,1);
    }
    return 0;
}
时间: 2024-07-31 15:46:28

Gym 100342F Move to Front的相关文章

Gym - 101617F :Move Away (圆的交点)

pro:给定N个圆,求离原点最远的点,满足它在N个圆里.输出这个距离.N<50; sol:关键点一定是圆与圆的交点. 圆与 圆心到原点的直线 的交点. 然后去验证这些关键点是否在N个圆内. 实际操作的时候需要考虑一些条件: 1,求圆的交点的时候,先判断是否内含或者相离. 2,求直线与圆的交点的时候,先判断是否圆心就在原点处. 3,有可能不存在相交的圆. 如何求圆与圆的交点: 用atan2求出t,余弦定理求出a,即可. #include<bits/stdc++.h> #define rep

关于方法的学习和应用,递归的应用

一:随机数(seed): package Demo; import javax.swing.JOptionPane; import java.util.Scanner; public class Seed { public static void main(String[]args) { String n=JOptionPane.showInputDialog("请输入你想打印的随机数的个数"); int m=Integer.parseInt(n); int[] a=new int [

c++ 实现数据库连接池

c++ 实现数据库连接池 自己尝试用c++ 新标准实现了数据库连接池,代码简化了很多. 思路: 将数据库的连接当作一个对象添加进list队列中,在连接池创建的时候就建立好队列,并添加自定义大小的连接对象,连接对象用智能指针来管理(现代c++中不应该出现delete语句),避免类似内存泄漏等内存问题,智能指针上用lambda表达式注册了delete删除函数来释放连接资源,及时归还,(其中用了std::move来转移list中的对象所有权到函数里的临时智能指针对象,当离开作用域时,自动释放.) 关于

同步并发操作之等待一次性事件

有时候需要用一些后台线程来完成计算,这些计算往往都是一次性的,线程计算完后便结束.这时候可以使用条件变量,但是有点浪费,我们只需要获取一次结果.C++标准库中有头文件<future>,很形象"未来",获取未来计算的结果. 使用std::async来启动一个异步任务.用std::future对象来存储异步任务返回的结果,这个对象存储结果.当我们需要结果时,只需调用get()方法.这时如果还没计算完毕,当前线程会阻塞. #include<future> #inclu

SGU 126

简单的BFS.无需任何优化. 利用一个结构体数组储存状态,三个量a,b,move分别表示A箱,B箱的球数以及移动次数. 注意对特殊情况的处理以及对不可能情况的判定: (1)两数之差为奇数,由题意,假设a<b,则移动球数为a,差的改变量为2a. 又有最终状态的前一步是两箱数目相等,差=0,所以不可能实现. (2)两数之差模4余2,但 初始球数都为偶数. 根据上面,类似地可以推导出不可能. (3)出现和前面相同的情况. - -这个就比较难处理- -数据范围在那里- - 总不能开个VIS[2^31][

Using FireMonkey Layouts

FireMonkey has many layout controls to choose from. Come learn the differences and how to use them to create dynamic, multi-platform user interfaces. FireMonkey Layouts with Delphi FireMonkey Layouts with C++Builder Understanding and using FireMonkey

线程安全的队列

template<typename T> class ThreadsafeQueue { private: mutable std::mutex _mut; std::queue<std::shared_ptr<T>> _dataQueue; std::condition_variable _dataCond; public: ThreadsafeQueue() = default; void push(T newValue) { std::lock_guard<

[转]缓存、缓存算法和缓存框架简介

以下内容转自:http://www.leexiang.com/cache-algorithm (转载请注明出处)-----------------------------------分割线---------------------------------------------- 引言 我们都听过 cache,当你问他们是什么是缓存的时候,他们会给你一个完美的答案,可是他们不知道缓存是怎么构建的,或者没有告诉你应该采用什么标准去选择缓存框架.在这边文章,我们会去讨论缓存,缓存算法,缓存框架以及哪

基于C++11的线程池,简洁且可以带任意多的参数

咳咳.C++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool)这个东西,在面试上多次被问到,一般的回答都是:"管理一个任务队列,一个线程队列,然后每次取一个任务分配给一个线程去做,循环往复." 貌似没有问题吧.但是写起程序来的时候就出问题了. 废话不多说,先上实现,然后再啰嗦.(dont talk, show me ur code !) 代码实现 1