SJTU OJ 1990 二哥听CD

SJTU OJ 1990 二哥听CD

原题链接

这道题用暴力解法也可以过,因为好感度每次都只加减1, 一般不会有太多的移动。
但是不经过好的优化,还是会超时的。
记录好每个CD移动之后的位置就可以了。

#include 
#include 
using namespace std;
struct cd{
    int index;
    int weight;
};
int n, m;
cd arr[2000005];
int movenode[2000005]={0};
void swap_(int & a, int & b){
    int c = a;
    a = b;
    b = c;
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i=1; i<=n; i++){
        scanf("%d", &(arr[i].weight));
        arr[i].index = i;
    }
    arr[0].weight = (1<<31);
    arr[n+1].weight = (1<<31)-1;
    int x, y;
    while (m--){
        scanf("%d%d", &x, &y);
        if (y == 1){
            int pos = (movenode[x] == 0 ? x : movenode[x]);
            arr[pos].weight++;
            while (arr[pos].weight > arr[pos+1].weight){
                movenode[arr[pos].index] = pos+1;
                movenode[arr[pos+1].index] = pos;
                swap_(arr[pos].weight, arr[pos+1].weight);
                swap_(arr[pos].index, arr[pos+1].index);
                pos++;
            }
        }
        else {
            int pos = (movenode[x] == 0 ? x : movenode[x]);
            arr[pos].weight--;
            while (arr[pos].weight <= arr[pos-1].weight){
                movenode[arr[pos].index] = pos-1;
                movenode[arr[pos-1].index] = pos;
                swap_(arr[pos].weight, arr[pos-1].weight);
                swap_(arr[pos].index, arr[pos-1].index);
                pos--;
            }
        }
        printf("%d\n", arr[1].index);
    }
    return 0;
}

更新:
用线段树维护最小值位置,代码如下:

#include 
#include 
using namespace std;
int n, m;
int arr[2000005];
int day[2000005];
int segTree[4000010];
inline void build(int node, int begin_, int end_)
{
    if (begin_ == end_)
        segTree[node] = begin_; /* 只有一个元素,节点记录该单元素 */
    else
    {
        /* 递归构造左右子树 */
        build(2*node, begin_, (begin_+end_)/2);
        build(2*node+1, (begin_+end_)/2+1, end_);
        /* 回溯时得到当前node节点的线段信息 */
        if (arr[segTree[2 * node]] < arr[segTree[2 * node + 1]])
            segTree[node] = segTree[2 * node];
        else
            segTree[node] = segTree[2 * node + 1];
    }
}
inline void Updata(int node, int begin_, int end_, int ind)/*单节点更新*/
{
    if( begin_ == end_) return;
    int m = (begin_ + end_) >> 1;
    if(ind <= m)
        Updata(node * 2,begin_, m, ind);
    else
        Updata(node * 2 + 1, m + 1, end_, ind);
    /*回溯更新父节点*/
    if (arr[segTree[node * 2]] < arr[segTree[node * 2 + 1]])
        segTree[node] = segTree[node * 2];
    else if (arr[segTree[node * 2]] > arr[segTree[node * 2 + 1]])
        segTree[node] = segTree[node * 2+1];
    else {
        if (day[segTree[node * 2]] > day[segTree[node * 2 + 1]])
            segTree[node] = segTree[node * 2];
        else
            segTree[node] = segTree[node * 2+1];
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i=1; i<=n; i++){
        scanf("%d", &arr[i]);
        day[i] = i;
    }
    int nowday = n+1;
    build(1, 1, n);
    int x, y;
    for (int i=0; iscanf("%d%d", &x, &y);
        day[x] = nowday++;
        arr[x] += y;
        Updata(1, 1, n, x);
        printf("%d\n", segTree[1]);
    }
    return 0;
}

如果有更好的做法,敬请指教。

你可能感兴趣的:(SJTUOJ)