zoukankan      html  css  js  c++  java
  • NOIP 模拟 $20; m z$

    题解

    很考验思维的一道题

    对于不同的任务点,发现如果 (x_{i-1}<x_i<x_{i+1})(x_{i-1}>x_i>x_{i+1}) 那么 (x_i) 这个位置的数就没用了

    将序列先扫一遍,合并不同的位置,然后将合并后的 (x_i->x_{i+1}) 按距离排序,再将询问序列从小到大排序,离线询问

    用一个 (map) 存储所有 (x_{i}->x_{i+1}) 的任务编号,二分查找当前点

    那么当一个长度大于这段区间了,它就会超出范围,要将它左右的区间和它合并

    注意:ans[c[t].id]=calc(ans[c[t].l),t++ 不能写成 ans[c[t].id]=calc(ans[c[t++].l),因为在高版本 c++ 中是从右往左编译的

    Code
    #include<bits/stdc++.h>
    #define ri register signed
    #define p(i) ++i
    using namespace std;
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
        template<typename T>inline void read(T &x) {
            ri f=1;x=0;register char ch=gc();
            while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
            while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
            x=f?x:-x;
        }
    }
    using IO::read;
    namespace nanfeng{
        #define node(id,x) (node){id,x}
        #define FI FILE *IN
        #define FO FILE *OUT
        template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
        template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
        typedef long long ll;
        static const int N=1e5+7;
        struct node{int id;ll x;}al[N];
        inline int operator<(const node &n1,const node &n2) {return n1.x>n2.x;}
        inline int cmp(node n1,node n2) {return n1.x<n2.x;}
        priority_queue<node> que;
        map<int,int> mp;
        int n,q,cnt,t=1;
        ll sum,dx[N],ans[N];
        inline ll calc(ll l) {
            if (mp.empty()) return 0;
            if (mp.begin()->second<0) return sum-(mp.size()-1)*l;
            return sum-mp.size()*l;
        }
        inline int main() {
            // FI=freopen("nanfeng.in","r",stdin);
            // FO=freopen("nanfeng.out","w",stdout);
            read(n),read(q);
            ri lst=0;
            for (ri i(1),x;i<=n;p(i)) {
                read(x);
                if (x==lst) continue;
                if (cnt&&(dx[cnt]<0&&x-lst<0||dx[cnt]>0&&x-lst>0)) dx[cnt]+=x-lst;
                else dx[p(cnt)]=x-lst;
                lst=x;
            }
            for (ri i(1),l;i<=q;p(i)) read(l),al[i].x=l,al[i].id=i;
            sort(al+1,al+q+1,cmp);
            for (ri i(1);i<=cnt;p(i)) {
                sum+=abs(dx[i]);
                mp[i]=dx[i];
                que.push(node(i,abs(dx[i])));
            }
                while(!que.empty()) {
                node tmp=que.top();que.pop();
                auto it=mp.lower_bound(tmp.id);
                if (it==mp.end()) continue;
                node nw=node(it->first,it->second);
                if (abs(nw.x)!=tmp.x||nw.id!=tmp.id) continue;
                while(t<=q&&tmp.x>al[t].x) ans[al[t].id]=calc(al[t++].x);
                auto bg=mp.begin();
                if (it!=mp.begin()) {
                    if (it!=prev(mp.end())) {
                        auto pr=prev(it),nx=next(it);
                        node tmpr=node(pr->first,pr->second);
                        node tmpn=node(nx->first,nx->second);
                        mp.erase(pr);mp.erase(nx);
                        sum-=abs(nw.x);
                        sum-=abs(tmpr.x);
                        sum-=abs(tmpn.x);
                        tmp.x=nw.x;
                        tmp.x+=tmpr.x;
                        tmp.x+=tmpn.x;
                        it->second=tmp.x;
                        tmp.x=abs(tmp.x);
                        sum+=tmp.x;
                        que.push(tmp);
                    } else {
                        sum-=abs(nw.x);
                        mp.erase(it);
                    }
                } else {
                    if (nw.x>0) {
                        if (it!=prev(mp.end())) {
                            auto nx=next(it);
                            node tmpn=node(nx->first,nx->second);
                            mp.erase(nx);
                            sum-=abs(nw.x);
                            sum-=abs(tmpn.x);
                            tmp.x=nw.x;
                            tmp.x+=tmpn.x;
                            if (tmp.x) {
                                it->second=tmp.x;
                                tmp.x=abs(tmp.x);
                                sum+=tmp.x;
                                que.push(tmp);
                            } else mp.erase(it);
                        } else {
                            sum-=abs(tmp.x);
                            mp.erase(it);
                        }
                    }
                } 
            }
            while(t<=q) ans[al[t].id]=calc(al[t++].x); 
            for (ri i(1);i<=q;p(i)) printf("%lld
    ",ans[i]);
            return 0;
        }  
    }
    int main() {return nanfeng::main();} 
    
  • 相关阅读:
    三阶魔方公式
    XML解析GData、XMLParser
    xib_cell布局适配高度
    SizeClass
    Storyboard界面传值
    Masonry(第三方库)的使—代码实现屏幕适配
    UITableView
    AFNetworking网上加载数据及JSON解析
    UICollectionView
    OC面向对象-多态
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15042889.html
Copyright © 2011-2022 走看看