当前位置:网站首页>7/26 思维+dp+后缀数组的学习
7/26 思维+dp+后缀数组的学习
2022-07-27 09:34:00 【钟钟终】
C. The Third Problem
题意:给定一个数组a,要求数组a和数组b相似,相似要求:对于任意一个区间,两数组的最小非负整数值相同,问有多少满足要求的数组b
思路:
1.记录数组a中0~n-1值所在的下标位置;
2.从0到n-1枚举i,并且记录0到i-1出现的数的最左和最右端点[L,R]
3.若a[i]出现在数i-1的最左和最右端点中,则r-l+1(表示数的个数,即区间长度)-i(固定位置值的个数)
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+5;
const int mod=1e9+7;
int n,a[N];
signed main()
{
int t;cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
int x;cin>>x;
a[x]=i;
}
int l=N,r=-1,ans=1;
for(int i=0;i<n;i++)
{
if(a[i]>=l&&a[i]<=r)
ans*=(r-l+1-i),ans%=mod;
l=min(a[i],l); //记录a[i]的左右端点值
r=max(a[i],r);
//cout<<l<<" "<<r<<" "<<ans<<endl;
}
cout<<ans<<endl;
}
return 0;
}
D. Increase Sequence
题意:将数组a中的值都转化为h,且左右区间只能出现一次。
思路:
1.若数组相邻数的差值大于1,则不存在方法满足题意得方法;a[i]=h-x
2.设置状态:dp[i]表示把a[1]~a[i]都变为0的最小操作次数
3.状态转移:
d=0,可用操作数为a[i]+1(1表示在i-1出结束,在i出开始)
d=-1,可用操作数为a[i-1],在i-1处结束
d==1,需要新开区间,dp[i]=dp[i-1]
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+5;
const int mod=1e9+7;
int n,h,a[N],dp[2005]; //dp[i]表示把a[1]~a[i]都变为0的最小操作次数
signed main()
{
cin>>n>>h;
for(int i=1;i<=n;i++)
{
int x;cin>>x;
a[i]=h-x;
}
dp[0]=1;
int flag=0;
n++;
for(int i=1;i<=n;i++)
{
int res=a[i]-a[i-1];
if(abs(res)>=2)
flag=1;
if(res==0)
dp[i]=dp[i-1]*(a[i]+1)%mod;
if(res==-1)
dp[i]=dp[i-1]*a[i-1]%mod;
if(res==1)
dp[i]=dp[i-1];
}
if(flag)
cout<<0<<endl;
else
cout<<dp[n]<<endl;
return 0;
}
后缀数组
模板:(注解在代码中)
const int N=1e5+5;
const int mod=1e9+7;
int n,k;
int rk[N]; //以i开头后缀的排名
char s[N];
int sa[N]; //表示sa[i]表示排名i的后缀的开头下标
//求解各个以i为起始下标的后缀字符串的排名
bool cmp(int i,int j)
{
if(rk[i]!=rk[j])
return rk[i]<rk[j];
int ri=(i+k<=n ? rk[i+k]:-1);
int rj=(i+k<=n ? rk[j+k]:-1);
return ri<rj
}
void getsa(int n,char *str)
{
int rk2[N];
for(int i=1;i<=n;i++)
sa[i]=i,rk[i]=s[i]; //利用ASCLL码
for(k=1;k<=n;k*=2)
{
sort(sa+1,sa+1+n;cmp);
rk2[sa[1]]=1;
for(int i=2;i<=n;i++)
rk2[sa[i]]=rk2[[sa[i-1]]]+cmp(sa[i-1],sa[i]);
for(int i=1;i<=n;i++)
rk[i]=rk2[i];
}
}
int ht[N] //维护数组rk相邻两个后缀的lcp(i-1和i的最长公共前缀)
void getht(int n,char *s)
{
for(int i=1;i<=n;i++)
rk[sa[i]]=1;
int h=0;
ht[1]=0;
for(int i=1;i<=n;i++)
{
int j=sa[rk[i]-1];
if(h>0)
h--;
for(;j+h<=n&&i+h<=n;h++)
if(s[j+n]!=s[i+h])
break;
ht[rk[i]]=h;
}
}
P4248 [AHOI2013]差异
本题所用知识:后缀数组+单调栈
i和j的最长公共前缀:i~j区间内ht[i]的最小值
套路:每个区间的区间最小值之和,使用单调栈解决。
ll[i]:表示往左看,小于等于h[i]的下标位置
rr[i]:表示从i往右看,小于等于h[i]的下标位置
算以h[i]为最小值的区间个数为:(i-ll[i])*(rr[i]-i)
可能数据更新了,这种做法会re,原因在与于cmp的排序规则增加了复杂度。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=5e5+5;
const int mod=1e9+7;
int n,k;
int rk[N],rk2[N]; //以i开头后缀的排名
char s[N];
int sa[N]; //表示sa[i]表示排名i的后缀的开头下标
//求解各个以i为起始下标的后缀字符串的排名
bool cmp(int i,int j)
{
if(rk[i]!=rk[j])
return rk[i]<rk[j];
int ri=(i+k<=n ? rk[i+k]:-1);
int rj=(j+k<=n ? rk[j+k]:-1);
return ri<rj;
}
void getsa(int n,char *str)
{
for(int i=1;i<=n;i++)
sa[i]=i,rk[i]=s[i]; //利用ASCLL码
for(k=1;k<=n;k*=2)
{
sort(sa+1,sa+1+n,cmp);
rk2[sa[1]]=1;
for(int i=2;i<=n;i++)
rk2[sa[i]]=rk2[sa[i-1]]+cmp(sa[i-1],sa[i]);
for(int i=1;i<=n;i++)
rk[i]=rk2[i];
}
}
int ht[N]; //维护数组rk相邻两个后缀的lcp(i-1和i的最长公共前缀)
void getht(int n,char *s)
{
for(int i=1;i<=n;i++)
rk[sa[i]]=i;
int h=0;
ht[1]=0;
for(int i=1;i<=n;i++)
{
int j=sa[rk[i]-1];
if(h>0)
h--;
for(;j+h<=n&&i+h<=n;h++)
if(s[j+h]!=s[i+h])
break;
ht[rk[i]]=h;
}
}
int top,ll[N],rr[N],sk[N],ans;
signed main()
{
scanf("%s",s+1);
n=strlen(s+1);
getsa(n,s);
getht(n,s);
top=1,sk[1]=1;
for(int i=2;i<=n;i++)
{
while(top&&ht[sk[top]]>ht[i])
rr[sk[top]]=i,top--;
ll[i]=sk[top];
sk[++top]=i;
}
while(top)
rr[sk[top]]=n+1,top--;
ans=n*(n-1)*(n+1)*1ll/2;
for(int i=1;i<=n;i++)
ans-=2*(i-ll[i])*(rr[i]-i)*ht[i];
printf("%lld\n",ans);
return 0;
}
P3809 【模板】后缀排序
对各个下标i的后缀进行排序后,输出排名为i的首字符的下标
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
int n,k;
int rk[N],rk2[N]; //以i开头后缀的排名
char s[N];
int sa[N]; //表示sa[i]表示排名i的后缀的开头下标
//求解各个以i为起始下标的后缀字符串的排名
bool cmp(int i,int j)
{
if(rk[i]!=rk[j])
return rk[i]<rk[j];
int ri=(i+k<=n ? rk[i+k]:-1);
int rj=(j+k<=n ? rk[j+k]:-1);
return ri<rj;
}
void getsa(int n,char *str)
{
for(int i=1;i<=n;i++)
sa[i]=i,rk[i]=s[i]; //利用ASCLL码
for(k=1;k<=n;k*=2)
{
sort(sa+1,sa+1+n,cmp);
rk2[sa[1]]=1;
for(int i=2;i<=n;i++)
rk2[sa[i]]=rk2[sa[i-1]]+cmp(sa[i-1],sa[i]);
for(int i=1;i<=n;i++)
rk[i]=rk2[i];
}
}
int ht[N]; //维护数组rk相邻两个后缀的lcp(i-1和i的最长公共前缀)
void getht(int n,char *s)
{
for(int i=1;i<=n;i++)
rk[sa[i]]=i;
int h=0;
ht[1]=0;
for(int i=1;i<=n;i++)
{
int j=sa[rk[i]-1];
if(h>0)
h--;
for(;j+h<=n&&i+h<=n;h++)
if(s[j+h]!=s[i+h])
break;
ht[rk[i]]=h;
}
}
int top,ll[N],rr[N],sk[N],ans;
signed main()
{
scanf("%s",s+1);
n=strlen(s+1);
getsa(n,s);
for(int i=1;i<=n;i++)
printf("%lld ",sa[i]);
printf("\n");
//getht(n,s);
return 0;
}
边栏推荐
- You haven't heard of such 6 question brushing websites, have you? Are you out?
- 如果mysql磁盘满了,会发生什么?还真被我遇到了!
- BGP federal experiment
- 七月集训(第09天) —— 二分查找
- Esp8266 Arduino programming example PWM
- July training (day 19) - binary tree
- 曝光一位出身寒门的技术大佬
- ArcGIS Pro publishing service
- 【CTF】ciscn_2019_es_2
- [cloud native] how can I compete with this database?
猜你喜欢

Lua函数嵌套调用

C# 给Word每一页设置不同文字水印

曝光一位出身寒门的技术大佬

监控神器:Prometheus 轻松入门,真香!
![[leetcode -- the first day of introduction to programming ability] basic data type [statistics of odd numbers within the range / average wage after removing the minimum wage and maximum wage)](/img/23/497c013d105d1906ae8a37dd4e18ad.png)
[leetcode -- the first day of introduction to programming ability] basic data type [statistics of odd numbers within the range / average wage after removing the minimum wage and maximum wage)

面试官:什么是脚手架?为什么需要脚手架?常用的脚手架有哪些?

快应用JS自定义月相变化效果

BGP的社团属性

好久不送书,浑身不舒服

The whole process of principle, simulation and verification of breath lamp controlled by FPGA keys
随机推荐
Proposed relocation! 211 the new campus of China University of Petroleum (East China) is officially opened!
[C language - zero foundation _ study _ review _ lesson 4] data types and operations
材料工程基础-重点
都什么年代了你还在用 Date
Sentinel 万字教程 | 文末送书
The command prompt cannot start mysql, prompting system error 5. Access denied. terms of settlement
系统架构之系统参数常量表:
命令提示符启动不了mysql,提示发生系统错误 5。拒绝访问。解决办法
STL container -- Application of set set
C# 给Word每一页设置不同文字水印
关于getter/setter方法问题
C language takes you to tear up the address book
给自己写一个年终总结,新年快乐!
[untitled]
NCCL (NVIDIA Collective Communications Library)
Google Earth engine app - maximum image synthesis analysis using S2 image
July training (day 15) - depth first search
The third day of learning C language
七月集训(第26天) —— 并查集
vscode使用remote-ssh连接以及连接失败的解决方法