zoukankan      html  css  js  c++  java
  • Gym101350 J Lazy Physics Cat

    参考博客:https://blog.csdn.net/lengqiu2015/article/details/76855681#reply

    题意

     给出一个长度为n的01串 我们定义F(x,y)是区间[x,y]内1的数量 请你计算有多少三元组(i,j,k)满足i<j<k,s[j]是1而且F[i,j]等于F[j,k] n<=200000

    分析

    一开始一直在想怎么枚举j然后计算方案数,发现这样我只能写O(N^2),GG。

    原来可以把题目转化一下,问这个串内有多少区间内有奇数个1(单独一个1或者1000或者0001这一类的都属于非法的)。

    然后可以用dp来解决(好像也可以不用dp?)

    dp[i][0]是以i为结尾的区间含有奇数个1的有多少

    dp[i][1]是以i为结尾的区间含有偶数个1的有多少

    那么转移就比较好想了:

    如果i是1,那么dp[i][1]=dp[i-1][0],dp[i][0]=dp[i-1][1]+1(奇数变偶数,偶数变奇数)

    如果i是0,那么dp[i][1]=dp[i-1][1],dp[i][0]=dp[i-1][0]+1

    这样把所有的dp[i][0]加起来,再减掉非法的区间就可以了~

    这个题要开long long。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 const int maxn=200000+10;
     8 char a[maxn];
     9 long long dp[maxn][2];
    10 
    11 int n,T;
    12 long long ans;
    13 
    14 int main(){
    15     scanf("%d",&T);
    16     for(int t=1;t<=T;t++){
    17         scanf("%d",&n);
    18         scanf("%s",a+1);
    19         ans=0;
    20         memset(dp,0,sizeof(dp));
    21         if(a[1]=='1'){
    22             dp[1][0]=1;
    23             dp[1][1]=0;
    24         }
    25         if(a[1]=='0'){
    26             dp[1][1]=1;
    27             dp[1][0]=0;
    28         }
    29         for(int i=2;i<=n;i++){
    30             if(a[i]=='1'){
    31                 dp[i][0]=dp[i-1][1]+1;
    32                 dp[i][1]=dp[i-1][0];
    33             }else if(a[i]=='0'){
    34                 dp[i][0]=dp[i-1][0];
    35                 dp[i][1]=dp[i-1][1]+1;
    36             }
    37         }
    38         for(int i=1;i<=n;i++){
    39             ans+=dp[i][0];
    40         }
    41         //下面去掉10000
    42         long long res=1,all=0;
    43 
    44         for(int i=n;i>=1;i--){
    45             if(a[i]=='1'){
    46                 all+=res;
    47                 res=1;
    48             }
    49             else
    50                 res++;
    51         }
    52         ans-=all;
    53         //下面去掉00001
    54         res=0,all=0;
    55         for(int i=1;i<=n;i++){
    56             if(a[i]=='1'){
    57                 all+=res;
    58                 res=0;
    59             }
    60             else
    61                 res++;
    62         }
    63         ans-=all;
    64         cout<<ans<<endl;
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    c#透明TextBox
    Twitter的分布式自增ID算法snowflake(雪花算法)
    关于权限设计的一点建议
    关于下载地址权限控制的一点问题解决方法
    数据结构_总结
    输出全排列输出
    数据结构_图总结
    n个括号对的所有可能情况
    根据表达式序列(前缀、中缀、后缀)构建表达式树
    Java finally语句是在try或catch的retrurn之前还是之后执行
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/8885925.html
Copyright © 2011-2022 走看看