zoukankan      html  css  js  c++  java
  • fjwc2019 D2T2 定价 (栈+set+贪心)

    #182. 「2019冬令营提高组」定价

    先瞄下数据范围

    对于所有数据,1n1000,1≤m≤10^91≤q≤500000 。 extbf{2 操作的个数不超过 1000。}

    $10^9$位,看起来挺吓人,咋维护每个可以为1的位鸭?

    再仔细看看,$q<=500000$,最多500000次操作,那么显然是对每一列,开个动态开点线段树或者平衡树维护。

    本题对数据结构要求不高,于是我们可以快捷地用set代替辣

    接下来我们考虑如何求出价格和的最小值

    2 操作的个数不超过 1000。

    这告诉我们可以愉快地在O(nlogn)内解决

    从左到右一列列扫过去........考虑贪心

    切一段ppt

    我们先总结一下贪心的时候在干啥。

    假设我们上一行有若干位为1,那么对于下一行,我们需要找到最高的为1位,满足这一行这位不能再为1了,我们就需要选取在这个位置之前的一个可以变成1的0,把它变成1,并把后面的位置全变成0。

    直接用bitset维护可以获得部分分。

    我们考虑使用一个栈维护当前的1,假设我们能找到最高的不能继续为1的位,我们就可以从这一位开始依次遍历前面的1,找到这个1之前第一个可以变成1的位置,如果这个位置在下一个1之前就是答案。

    举个栗子

    设前面$i$列处理完后,已知第$i$列的最小值$=(10101101)_{2}$

    而第$i+1$列允许为$1$的位(从左到右,从$1$开始)有第$1,2,3,4,5,6$位

    加入没有限制,那么第$i+1$列的最优解$=(10101110)_{2}$

    但是允许为$1$的位不包括第$7$位鸭

    于是我们就只能再向左找,找到第$4$位

    把第$4$位改为$1$,并将右边所有位改为$0$

    最后第$i+1$列的最优解$=(10110000)_{2}$

    即为:

    $a[i]=(10101101)_{2}$

    $a[i+1]=(10110000)_{2}$

    然后顺便维护下答案就ok了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<set>
    
    namespace IO {
        const int lim = (1 << 20) + 500;
    
        char buf[lim + 5], *S, *T;
    
        inline char gc() {
            if (S == T) {
                T = (S = buf) + fread(buf, 1, lim, stdin);
                if (S == T) return EOF;
            }
            return *S++;
        }
    
        inline int read() {
            int x; char c; bool f;
            for (f = 0; (c = gc()) < '0' || c > '9'; f = c == '-');
            for (x = c ^ '0'; (c = gc()) >= '0' && c <= '9'; x = (x << 1) + (x << 3) + (c ^ '0'));
            return f ? -x : x;
        }
    }
    using namespace IO;//快读是题目给的(逃
    
    using namespace std;
    const int mod=1e9+7;
    int n,m,q,stk[500005],v[500005],tp;
    set <int> s[1005];
    set <int>::iterator it;
    int Pow(int x,int y){
        int re=1;
        for(;y;y>>=1,x=1ll*x*x%mod)
            if(y&1) re=1ll*re*x%mod;
        return re;
    }
    int solve(){
        int re=0; tp=0;
        for(int i=1,j;i<=n;++i){
            stk[tp+1]=m+1;
            for(j=1;j<=tp&&s[i].count(stk[j]);++j);//这一位填不了的话就从这位开始找
            tp=j-1;
            for(;;){
                it=s[i].upper_bound(stk[tp+1]-1);
                if(it==s[i].begin()) return -1;
                --it;
                if(*it>stk[tp]){stk[++tp]=*it; break;}
                if(!tp) return -1;
                --tp;
            }
            v[tp]=v[tp-1]+Pow(2,m-stk[tp]);//上个的答案(用数组维护)加上这一位
            if(v[tp]>=mod) v[tp]-=mod;
            re+=v[tp];
            if(re>=mod) re-=mod;
        }return re;
    }
    int main(){
        freopen("price.in","r",stdin);
        freopen("price.out","w",stdout);
        n=read(); m=read(); q=read();
        int q1,q2;
        while(q--){
            if(read()==1){
                q1=read(); q2=read();
                if(s[q1].count(q2)) s[q1].erase(q2);
                else s[q1].insert(q2);
            }else printf("%d
    ",solve());
        }return 0;
    }
  • 相关阅读:
    Viusal Studio 2022 正式版安装秘钥
    关于云计算,云存储,和自己开发的云存储的小工具
    网盘工具比较,以及自己开发的网盘工具
    VARIANT及相关类
    关于 BSTR, CComBSTR and _bstr_t
    如何真正发挥Google Docs的威力
    ORM框架EntitysCodeGenerate自定义分页查询及快捷执行SQL(CreateSQL)示例
    关于Java Servlet的中文乱码
    ORM框架VB/C#.Net实体代码生成工具(EntitysCodeGenerate) 【ECG】4.3 介绍
    通用JS验证框架(ChkInputs)概述
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10440953.html
Copyright © 2011-2022 走看看