BZOJ3764 : Petya的序列

首先如果一段连续子序列里没有任何幸运数,那么显然可以缩成一个点。

设幸运数个数为$m$,那么现在序列长度是$O(m)$的,考虑暴力枚举$R_1$,然后从右往左枚举$L_1$。

每次碰到一个幸运数,就将它删去,维护出被删的数它左边右边连续能到的位置,然后用组合数计算贡献。

考虑给每个被删数字一个删除时间$b_i$,那么等价于询问它左边右边第一个$b$小于$b_i$的位置,可以通过两遍单调栈得到。

时间复杂度$O(m^2)$。

#include<cstdio>
#include<algorithm>
typedef unsigned long long ll;
const int N=2005,M=100010;
int n,m,p,lim,i,j,a[N],v[N],s[N],g[M],nxt[N],vis[M];
int b[N],c[N],cnt,pos[N],ex,L[N],R[N],q[N],t;
ll f[M],C[M][5],sum[N],ans;
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
inline int trans(int x){
  if(x==0)return -1;
  int t=x;
  while(x){
    int y=x%10;
    if(y!=4&&y!=7)return -1;
    x/=10;
  }
  return t;
}
inline int lower(int x){
  int l=1,r=n,mid,t;
  while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
  return t;
}
inline int add(int x,int y){nxt[y]=g[x];g[x]=y;}
inline void del(int x){
  if(x<0)return;
  if(vis[x])return;
  vis[x]=1;
  for(int i=g[x];i;i=nxt[i])if(i>lim){
    b[i]=++cnt;
    c[cnt]=i;
    if(i<ex)ex=i;
  }
}
inline ll cal(int l,int x,int r){return f[s[x-1]-s[l-1]]+f[s[r]-s[x]]-f[s[r]-s[l-1]];}
int main(){
  read(n);
  for(i=1;i<=n;i++)f[i]=1ULL*i*(i+1)/2ULL;
  for(i=1;i<=n;i++){
    C[i][1]=i;
    if(i<=4)C[i][i]=1;
    for(j=2;j<=4&&j<i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];
  }
  while(n--){
    read(i);
    i=trans(i);
    if(~i||a[m]>=0)a[++m]=i;else a[m]--;
  }
  for(i=1;i<=m;i++){
    if(a[i]>0)b[++p]=a[i],v[i]=1;else v[i]=-a[i];
    s[i]=s[i-1]+v[i];
  }
  if(p>1)for(std::sort(b+1,b+p+1),n=0,i=1;i<=p;i++)if(b[i]!=b[i-1])b[++n]=b[i];
  for(i=1;i<=m;i++)if(a[i]>0)add(a[i]=lower(a[i]),i);
  for(lim=1;lim<=m;lim++){
    for(cnt=i=0;i<=n;i++)vis[i]=0;
    ex=m+1;
    for(i=lim+1;i<=m;i++)b[i]=N;
    for(i=lim;i;i--){
      del(a[i]);
      pos[i]=cnt;
      if(i<lim){
        ans+=(C[v[lim]][3]+C[v[lim]][2]*(s[ex-1]-s[lim]+1))*v[i];
      }else{
        ans+=C[v[i]][2]+C[v[i]][3]*2ULL+C[v[i]][4];
        ans+=(C[v[i]][2]+C[v[i]][3])*(s[ex-1]-s[lim]);
      }
    }
    for(b[q[t=0]=lim]=0,i=lim+1;i<=m;q[++t]=i++){
      while(b[q[t]]>=b[i])t--;
      L[i]=q[t]+1;
    }
    for(b[q[t=0]=m+1]=0,i=m;i>lim;q[++t]=i--){
      while(b[q[t]]>=b[i])t--;
      R[i]=q[t]-1;
    }
    sum[0]=f[s[m]-s[lim]];
    for(i=1;i<=cnt;i++)sum[i]=sum[i-1]+cal(L[c[i]],c[i],R[c[i]]);
    ans+=sum[pos[lim]]*f[v[lim]];
    for(i=lim-1;i;i--)ans+=sum[pos[i]]*v[i]*v[lim];
  }
  return printf("%llu",ans),0;
}

  

时间: 2024-08-09 19:47:18

BZOJ3764 : Petya的序列的相关文章

codevs3250 操作序列

题目描述 Description Petya是一个非常好玩孩子.他很无聊,因此他开始玩下面的游戏: 他得到一个长度为N的整数序列,他会对这些数字进行操作,他可以把某个数的数值加1或者减1(当然他可以对同一个数操作很多次).他的目的是使得数列非递减,即在修改之后,数列满足a1≤a2≤...≤aN . 请你告诉他,他最少要操作多少次. 输入描述 Input Description 第1行一个整数n. 第2行n个整数 a1.a2.…….an,每两个整数之间用一个空格隔开 输出描述 Output Des

如何理解“字符串是一组由16位组成的不可变的有序序列”

疑惑点: 1.16位 2.不可变 3.有序序列 解惑: 1.16位指的是:字符串每个字符所占用的空间为16bits 比特(2 bytes);这是因为JS采用的是unicode编码,每个字符需要2个字符. 2.不可变指的是: 字符串对象一旦创建出来,便不能被更改.这可能有些难理解,但事实确实如此.你可能会认为s+='1' 只是在 s 后面增加一个元素 1 而已,但事实是: 先将 s 拷贝一份,记为 temp 在 temp 末尾加上'1' 将 s 变量指向 temp,并删去原来的s 这一特性,可以从

BZOJ 3992 【SDOI2015】 序列统计

题目链接:序列统计 我来复习板子了--这道题也是我写的第一发求原根啊? 求原根方法: 从小到大依次枚举原根.设当前枚举的原根为\(x\),模数为\(p\),\(p-1\)的质因数分别为\(p_1,p_2,\dots,p_m\),则只需检验\(x^{\frac{p}{p_i}}\equiv1 \pmod{p}\)是否成立即可.如果成立则\(x\)不是原根. 然后这道题朴素\(dp\)就不讲了.设\(m\)的原根为\(g\),那么把每个数表示成\(g^k\)的形式就可以乘法变加法了,就成为了\(NT

k序列和

二分答案是参数搜索的一个改善.是这样,对于一个问题,如果它的答案具有单调性质(即如果i不可行,那么大于i的解都不可行,而小于i的解有可能可行),进而用二分的方法枚举答案,再判断答案是否可行,直到求到符合条件为止.例如:问题的答案范围是1到w之间的一个整数,求最小解,那么我们设s=1,t=w,之后mid=(s+t)整除2.然后判断当解是mid的时候这个问题能不能解决,如果能解决则和最优解比较,并且范围缩小到s到mid-1之间(因为即使这个范围没有解,那么mid是最小解):如果不能解决问题,则最小解

3、创建数据库、表空间、权限管理、表、约束、序列

一.dos常用命令 右键→标记→选中要复制的内容→右击就可以完成赋值 ↑表示找前面代码 data 查看日志time 查看时间cls 清屏exit 退出regedit 注册表taskmgr 任务管理器compmgmt.msc计算机管理mspaint 画图板 开始 运行 命令 集锦 --------------------------------write----------写字板 notepad--------打开记事本shrpubw--------创建共享文件夹 calc-----------启

数据结构(括号序列,线段树):ZJOI 2007 捉迷藏

[题目描述] Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达. 游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯.在起初的时候,所有的灯都没有被打开.每一次,孩子们只会躲 藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯.为了评估某一次

使用RNN解决NLP中序列标注问题的通用优化思路

/* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/ author: 张俊林 序列标注问题应该说是自然语言处理中最常见的问题,而且很可能是最而没有之一.在深度学习没有广泛渗透到各个应用领域之前,传统的最常用的解决序列标注问题的方案是最大熵.CRF等模型,尤其是CRF,基本是最主流的方法.随着深度学习的不断探索和发展,很可能RNN模型会取代CRF的传统霸主地位,会成为解决序列标注问题的标配解决方案. 本文主要抽象出利用RNN解决序列标注问题的通用优化思路.这个RNN优化思路应该

BZOJ 1251 序列终结者(Splay)

题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧.[问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将 [L, R] 这个区间内的所有数加上 V. 2. 将 [

验证给定序列是否是BST的preoder序列

from leetcode https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/ 比如序列 2, 1, 3 是如下图的BST的preorder 序列: 但是2, 3, 1就不会是一个preorder序列: 先复习一下BST,给定一个节点,其左子树的所有节点都小于该节点,右子树的所有节点都大于该节点:preorder序列是指在遍历该BST的时候,先记录根节点,再遍历左子树,然后遍历右子树:所以一个