zoukankan      html  css  js  c++  java
  • 选择客栈 递推

    写题思路一定要清晰后再动键盘,否则肯定死得很惨。。(被绿题虐系列

    题目要求所有满足颜色相同且两点间存在一点小于等于某值的方案数。

    显然2e6的数据一般是O(n)的做法,所以从一开始就在想递推式,然后由于思路比较乱,一直没有写出来,直到今天才好好理了理思路:

    对于读入到的一点,颜色为cl,价格为wi,对价格进行分类讨论:

    如果价格符合要求,那么该点前的所有点与该点及该点后点的连线都可以利用这一点,所以跨越该点的连线都是合法的。所以答案应加上这一点之前所有的同色点数。

    如果价格不符合要求,那么该点只能利用之前的合法点与前面的同色点连线,这样对答案的贡献就是之前所有在最后一个合法点之前的同色点数目。

    发现如果每加入一个合法点时都立即更新每种颜色的合法值所需要的时间复杂度为O(k),不符合要求,所以想到可以借助懒标记思想仅仅记录最后一个合法点的位置和每种颜色最后一个不合法点的位置,在查询到某种颜色时在进行更新即若该颜色最后一个不合法点的位置小于等于最后一个合法点的位置则把这些不合法点数加入合法点数中,这样就可以避免了大量的无用计算.

    code:

     1 #include<iostream>
     2 #include<cstdio>
     3 #define rep(i,a,n) for(register int i = a;i <= n;++i) 
     4 using namespace std;
     5 
     6 int read(){int x;scanf("%d",&x);return x;}
     7 
     8 const int Maxk = 510;
     9 int cn1[Maxk],cn2[Maxk],la[Maxk];
    10 int ans,cl,wi,n,p,k;
    11 
    12 int main(){
    13     n = read(),k = read(),p = read();
    14     
    15     rep(i,1,n){
    16         cl = read(),wi = read();
    17         if(wi <= p){
    18             cn1[cl] += cn2[cl],cn2[cl] = 0;
    19             ans += cn1[cl];
    20             cn1[cl]++;
    21             la[k] = i;
    22         }
    23         else{
    24             if(la[cl] < la[k]){
    25                 cn1[cl] += cn2[cl];
    26                 cn2[cl] = 0;
    27             }
    28             cn2[cl]++,la[cl] = i;
    29             ans += cn1[cl];
    30         }
    31     }
    32     
    33     cout << ans;
    34 return 0;
    35 }
  • 相关阅读:
    hiho_1081_最短路径1
    hiho_1079_离散化
    hiho_1078_线段树区间修改
    hiho_1069_最近公共祖先3
    【.netcore学习】.netcore添加到 supervisor 守护进程自启动报错
    【.NetCore学习】ubuntu16.04 搭建.net core mvc api 运行环境
    【.NetCore学习】ASP.NET Core EF Core2.0 DB First现有数据库自动生成实体Context
    【vue基础学习】vue.js开发环境搭建
    【vue学习】vue中怎么引用laydate.js日期插件
    【年终总结】个人的2017年年终总结
  • 原文地址:https://www.cnblogs.com/Wangsheng5/p/11862597.html
Copyright © 2011-2022 走看看