zoukankan      html  css  js  c++  java
  • luogu1110[ZJOI2007]报表统计

    思路

    这里的初始化就不讲了,看完操作讲解就应该明白了,再不行就去看代码

    对于操作1

    由于操作2的需要,vector[n]存下数

    对于操作2的维护

    查询相邻两个元素的之间差值(绝对值)的最小值
    先把所有答案存入一个小头堆里
    比如 a,c之间你要插入b
    那么,你就要删除|c-a|,然后加入|a-b|,|c-b|
    之后的堆顶就是ans啦
    对于支持删除的小头堆,我只会fhqtreap代替
    但我也不想写, 因为太麻烦了
    那么,我们能不能用STL自带的priority_queue
    当然是可行的
    维护两个堆,x,y
    ans存入x中,需要删除的存入y中
    每次更改的时候,改存的放入x,改删的放入y
    每当x.top()==y.top(),就一起删掉,(注意!y.empty())

    对于操作3的维护

    查询所有元素中最接近的两个元素的差值(绝对值)
    每次修改一个数,对最优答案都不会有坏的影响(显然)
    那好的影响是啥
    就是他和她的前驱,后继的差(显然)
    注意前驱,后继的存在性

    错误及其优化

    最近老是不动脑子了(或者根本没脑子?)
    insert操作查找前驱后继的时候可以省去find操作

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int maxn=5e5+7;
    const int inf=0x3f3f3f3f;
    inline int read() {
        int x=0,f=1;char s=getchar();
        for(; s>'9'||s<'0'; s=getchar()) if(s=='-') f=-1;
        for(; s>='0'&&s<='9'; s=getchar()) x=x*10+s-'0';
        return x*f;
    }
    int n,m,rt,ans2=inf,a[maxn],cnt;
    struct node {
        int ch[2],val,fa,siz;
    } e[maxn*2];
    vector<int> x[maxn];
    priority_queue<int, vector<int>, greater<int> >  ans1,delet;
    inline int abs(int a) {return a>0?a:-a;}
    inline void pushup(int x) {e[x].siz=e[e[x].ch[0]].siz+e[e[x].ch[1]].siz+1;}
    inline void rotate(int x) {
        int y=e[x].fa,z=e[y].fa,k=e[y].ch[1]==x;
        e[x].fa=z;
        e[z].ch[e[z].ch[1]==y]=x;
        e[y].ch[k]=e[x].ch[k^1];
        e[e[x].ch[k^1]].fa=y;
        e[y].fa=x;
        e[x].ch[k^1]=y;
        pushup(x);pushup(y);
    }
    void splay(int x,int goal) {
        while(e[x].fa!=goal) {
            int y=e[x].fa,z=e[y].fa;
            if(z!=goal)(e[y].ch[1]==x)^(e[z].ch[1]==y) ? rotate(y):rotate(x);
            rotate(x);
        }
        if(!goal) rt=x;
    }
    void find(int a) {
        int now=rt;
        while(e[now].ch[e[now].val<a]&&e[now].val!=a)
            now=e[now].ch[e[now].val<a];
        splay(now,0);
    }
    void insert(int x) {
        int now=rt,fa=0;
        while(now&&e[now].val!=x)
            fa=now,now=e[now].ch[e[now].val<x];
        now=++cnt;
        if(fa) e[fa].ch[e[fa].val<x]=now;
        e[now].val=x;
        e[now].fa=fa;
        e[now].siz=1;
        splay(now,0);
    }
    inline int qq(int x) {
        if(e[rt].val<x) return rt;
        int now=e[rt].ch[0];
        while(e[now].ch[1]) now=e[now].ch[1];
        return now;
    }
    inline int hj(int x) {
        if(e[rt].val>x) return rt;
        int now=e[rt].ch[1];
        while(e[now].ch[0]) now=e[now].ch[0];
        return now;
    }
    int build(int l,int r,int fa) {
        if(l>r) return 0;
        int mid=(l+r)>>1,p=++cnt;
        e[p].val=a[mid];
        e[p].fa=fa;
        e[p].siz=1;
        e[p].ch[0]=build(l,mid-1,p);
        e[p].ch[1]=build(mid+1,r,p);
        pushup(p);
        return p;
    }
    int main() {
        n=read(),m=read();
        FOR(i,1,n) a[i]=read(),x[i].push_back(a[i]);
        //ans1
        FOR(i,2,n) ans1.push(abs(x[i][0]-x[i-1][0]));
        //ans2
        sort(a+1,a+1+n);
        FOR(i,2,n) ans2=min(abs(a[i]-a[i-1]),ans2);
        a[0]=-inf,a[n+1]=inf;
        rt=build(0,n+1,0);
        char s[10];
        FOR(i,1,m) {
            scanf("%s",s);
            if(s[4]=='R') {
                int a=read(),b=read();
                //ans1
                if(a!=n) delet.push(abs(x[a][x[a].size()-1]-x[a+1][0]));
                x[a].push_back(b);
                if(a!=n) ans1.push(abs(x[a][x[a].size()-1]-x[a+1][0]));
                ans1.push(abs(x[a][x[a].size()-1]-x[a][x[a].size()-2]));
                while(delet.size()&&ans1.top()==delet.top()) ans1.pop(),delet.pop();
                //ans2
                find(b);
                if(e[rt].val==b) {ans2=0;continue;}
                insert(b);
                int x=e[qq(b)].val,y=e[hj(b)].val;
                ans2=min(ans2,min(abs(x-b),abs(y-b)));
            } else if(s[4]=='G') {
                cout<<ans1.top()<<"
    ";
            } else if(s[4]=='S') {
                cout<<ans2<<"
    ";
            }
        }
        return 0;
    } 
    
  • 相关阅读:
    HDU 1165 Eddy's research II (推公式)
    HDU 1394 Minimum Inversion Number (线段树&&暴力)
    HDU 2845 Beans (最大不连续子序列和)
    CodeForces 369A Valera and Plates( 水)
    HDU 1241 Oil Deposits(dfs)
    hdu 1016 Prime Ring Problem(dfs)
    hdu 5138 CET-6 test(水)
    ZOJ 3693 Happy Great BG(卡精度)
    HDU 1028 Ignatius and the Princess III(dp 母函数)
    CodeForces 432B Football Kit(水)
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10095024.html
Copyright © 2011-2022 走看看