SJTU OJ 1990 二哥听CD

来源:互联网 发布:网页调用excel数据 编辑:程序博客网 时间:2024/05/21 10:40

SJTU OJ 1990 二哥听CD

原题链接

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

#include <iostream>#include <cstdio>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 <iostream>#include <cstdio>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; i<m; i++){        scanf("%d%d", &x, &y);        day[x] = nowday++;        arr[x] += y;        Updata(1, 1, n, x);        printf("%d\n", segTree[1]);    }    return 0;}

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