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 }
  • 相关阅读:
    SQLSERVER查询所有数据库名,表名,和字段名
    SQL通过拆分某字段中的内容来实现与对应表连接查询
    [SPOJ]CIRU 圆并
    有关反演和GCD
    docker部署 jenkins
    mongoDB学习记录(二)
    docker动态修改容器限制
    ORACLE数据库误操作DELETE并且提交数据库之后如何恢复被删除的数据
    用8个命令调试Kubernetes集群
    db2服务器linux的cache过高原因
  • 原文地址:https://www.cnblogs.com/Wangsheng5/p/11862597.html
Copyright © 2011-2022 走看看