zoukankan      html  css  js  c++  java
  • CF526F Pudding Monsters

    Solution

    如果一个 (k*k) 的矩阵里放满了 (k) 个数,容易发现横坐标和纵坐标都是连续的,我们需要利用好这个性质,那么不妨按横坐标排序,之后只有相连的几个点会造成贡献。对于一个区间 ([l,r]),如果它是合法的,当且仅当区间长度等于值域长度(由于合法时值域一定是连续的),即

    [r-l+1=max limits_{lleq ileq r} {y_i}-min limits_{lleq ileq r} {y_i}+1 ]

    对于一个确定的 (r) 只需要统计方程

    [max limits_{lleq ileq r} {y_i}-min limits_{lleq ileq r} {y_i}-r+l=0 ]

    成立的个数。可以用线段树对每一个位置维护这个值。考虑到没有重复的数,值域长度一定大于等于区间长度,那么上式左边会恒大于等于 0,而 (r) 这个单独的位置一定有一个合法解,即会出现 0,所以只需统计区间最小值(0)出现次数就行了。

    对于线段树的维护,考虑增量法。当从 (r) 转移到 (r+1)(r) 会加 1,那么 ([1,r]) 的所有位置的数减 1。对于 (min)(max) 用单调栈维护一下,弹栈时对数列更新一下最大值最小值信息即可。

    考虑到每次弹栈入栈会 (modify) 一次,所以复杂度 (O(nlog n))

    #include<stdio.h>
    #define lid id<<1
    #define rid id<<1|1
    #define N 300007
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    int s[N<<2],num[N<<2],tag[N<<2];
    
    void build(int id,int lf,int rf){
        s[id]=1;
        if(lf==rf) return ;
        int mid=(lf+rf)>>1;
        build(lid,lf,mid);
        build(rid,mid+1,rf);
        s[id]=s[lid]+s[rid];
    }
    
    inline int min(int x,int y){return x<y? x:y;}
    void push(int id,int v){num[id]+=v,tag[id]+=v;}
    void pushdown(int id){push(lid,tag[id]),push(rid,tag[id]),tag[id]=0;}
    void modify(int id,int lf,int rf,int l,int r,int val){
        if(l<=lf&&rf<=r) push(id,val);
        else{
            int mid=(lf+rf)>>1;
            if(tag[id]) pushdown(id);
            if(l<=mid) modify(lid,lf,mid,l,r,val);
            if(r>mid) modify(rid,mid+1,rf,l,r,val);
            num[id]=min(num[lid],num[rid]);
            s[id]=(num[id]==num[lid]? s[lid]:0)+(num[id]==num[rid]? s[rid]:0);
        }
    }
    
    int n,ma[N],mi[N],t1=0,t2=0,a[N];
    int main(){
        n=read();
        for(int i=1;i<=n;i++) a[read()]=read();
        build(1,1,n);
        long long ans=0;
        for(int i=1;i<=n;i++){
            modify(1,1,n,1,i,-1);
            while(t1&&a[ma[t1]]<a[i])
                modify(1,1,n,ma[t1-1]+1,ma[t1],a[i]-a[ma[t1]]),t1--;
            while(t2&&a[mi[t2]]>a[i])
                modify(1,1,n,mi[t2-1]+1,mi[t2],a[mi[t2]]-a[i]),t2--;
            ma[++t1]=mi[++t2]=i;
            ans+=1LL*s[1];
        }
        printf("%lld",ans);
    }
    
  • 相关阅读:
    Martix工作室考核题 —— 打印一个菱形
    Martix工作室考核题 —— 打印一个菱形
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 打印九九乘法表
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第三题
    Martix工作室考核题 —— 201938 第一题
    fiddler模拟发送post请求
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14157289.html
Copyright © 2011-2022 走看看