zoukankan      html  css  js  c++  java
  • Noip2011 提高组 选择客栈

    P1311 选择客栈

    直通

    思路:

      ①看题,我们可以发现一个显然的性质,即当最左边的客栈向右移动时,最右边的客栈时单调向右的,并且右端点往右的客栈也符合要求。(因为只要左侧有一个满足的,右边的自然可以选)

      不妨将每种颜色的宾馆分别放到 vector 中。

      然后在每个 vector 中枚举左端点,维护一个单调指针来确定右端点 (vector中的下标)。

      我们接下来就要快速判断一段区间是否合法,我们开一个ok数组,表示从i点开始最近的满足条件的位置(不考虑颜色)。

        这样的话转移就是:

                ok[i]=i;(p[i]<=P),反之:ok[i]=ok[i+1];

                需要注意的是ok[n+1]=n+1;

                表示如果p[n]>P则p[n]=p[n+1]=n+1,即不合法

      ②大模拟,详细看代码

    坑点:

      注意输入顺序qwq

    上代码:

    1)vector版

    #include <iostream>
    #include <cstdio>
    #include <vector>
    using namespace std;
    
    const int K = 50;
    const int N = 200001;
    int n,k,p,ans;
    int w[N],ok[N];
    vector<int>v[K];
    
    void getnxt() {
        ok[n+1]=n+1;
        for(int i=n; i>=1; i--) {
            if(w[i]<=p) ok[i]=i;
            else ok[i]=ok[i+1]; 
        }
    }
    
    int main() {
        scanf("%d%d%d",&n,&k,&p);
        for(int i=1,x; i<=n; i++) {
            scanf("%d%d",&x,&w[i]);
            v[x].push_back(i);
        }
        getnxt();
        for(int i=0,d,s; i<k; i++) {
            d=0;
            s=v[i].size(); //i客栈连接的s个客栈 
            for(int j=0; j<s; j++) {
                d=max(d,j+1); //当前枚举到的最右端的客栈所在色调的编号是多少 
                while(ok[v[i][j]]>v[i][d] && d<s) {
                    d++;
                } //这里不太懂... 
                ans+=s-d;
            }
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    2)纯模拟版

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    const int K = 101;
    int n,k,p,ans;
    int precnt[K],ok[K],last[K];
    //precnt[x] i点前颜色为x的客栈数
    //ok[x]     i点前满足能有价格<=p的客栈的颜色为x的客栈数
    //last[x]   i点 前一个颜色 为x的点的编号
    
    int main() {
        scanf("%d%d%d",&n,&k,&p);
        for(int i=1,tmp,x,y; i<=n; i++) {
            scanf("%d%d",&x,&y);
            if(y<=p) tmp=i; //记录下来当前色调的可行的最右客栈编号 
            if(tmp>=last[x]) ok[x]=precnt[x];
            ans+=ok[x];
            precnt[x]++; //不管是不是可以满足条件 
            last[x]=i; 
        }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    .NET 4.5 异步IO
    使用MANIFEST.MF文件来track War包做持续部署
    .NET 4.5 压缩
    自定义实现URL重写 04.18
    对.Net Framework的认识
    那点所谓的分布式——memcache
    不能选择FreeTextBox下拉列表框
    实战架构设计
    LoadRunner压力测试心得总结
    JavaScript的模块化:封装(闭包),继承(原型)
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/7763997.html
Copyright © 2011-2022 走看看