双栈模拟队列
使用情况:
可以使用双指针,但是这道题目如果带删除并不好实现,这时可以考虑用两个栈模拟队列解决问题。
时间复杂度与普通的双指针没有区别,但是每一个值需要存储一个可能很大的状态,比如一个完整的背包,导致空间复杂度可能会比较大
具体原理就是用栈来模拟队列,加入时用一个栈,每个加入的值记录的状态都需要继承转移上一次的栈顶状态,删除时如果另一个栈删完了,把原栈的值全部加入新栈,如何转移同上。
这种双指针的缺陷在于需要满足状态符合结合律,否则在查询时将两个栈栈顶进行处理会产生问题(暂时还想不到常见例子)
板子+板子题目
作差维护gcd即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,a[200005],d[200005];
int gcd(int x,int y){
if(!y)return x;
return gcd(y,x%y);
}
struct Q{
int top1,top2;
pair<int,int> st1[200005],st2[200005];
void push(int x){
if(!top2)st2[++top2]={x,d[x]};
else {
int tmp=gcd(d[x],st2[top2].second);
st2[++top2]={x,tmp};
}
}
void pop(){
if(top1){
top1--;
return;
}
while(top2){
if(!top1)st1[++top1]={st2[top2].first,d[st2[top2].first]};
else {
int tmp=gcd(d[st2[top2].first],st1[top1].second);
st1[++top1]={st2[top2].first,tmp};
}
top2--;
}
top1--;
}
int check(){
if(!top2)return st1[top1].second;
if(!top1)return st2[top2].second;
return gcd(st1[top1].second,st2[top2].second);
}
}q;
signed main(){
cin>>t;
while(t--){
q.top1=q.top2=0;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++)d[i]=abs(a[i+1]-a[i]);
int l=1,ans=0;
for(int i=1;i<n;i++){
q.push(i);
while(q.check()==1)q.pop(),l++;
ans=max(ans,i-l+2);
}
cout<<ans<<endl;
}
return 0;
}
Array Stabilization (GCD version)
还是维护gcd
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,a[200005];
int gcd(int x,int y){
if(!y)return x;
return gcd(y,x%y);
}
struct Q{
int top1,top2;
pair<int,int> st1[200005],st2[200005];
void push(int x){
if(!top2)st2[++top2]={x,a[x]};
else {
int tmp=gcd(a[x],st2[top2].second);
st2[++top2]={x,tmp};
}
}
void pop(){
if(top1){
top1--;
return;
}
while(top2){
if(!top1)st1[++top1]={st2[top2].first,a[st2[top2].first]};
else {
int tmp=gcd(a[st2[top2].first],st1[top1].second);
st1[++top1]={st2[top2].first,tmp};
}
top2--;
}
top1--;
}
int check(){
if(!top2)return st1[top1].second;
if(!top1)return st2[top2].second;
return gcd(st1[top1].second,st2[top2].second);
}
}q;
signed main(){
cin>>t;
while(t--){
q.top1=q.top2=0;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int tmp=a[1];
for(int i=1;i<=n;i++)tmp=gcd(tmp,a[i]);
int r=2*n,ans=0;
for(int i=n;i>=1;i--)q.push(i);
for(int i=n;i>=1;i--){
q.push(i);
while(q.check()==tmp)q.pop(),r--;
ans=max(ans,r-i+1);
}
cout<<ans<<endl;
}
return 0;
}
只要胆子大,空间开的下
直接双栈双指针内维护一个背包即可
#include<bits/stdc++.h>
using namespace std;
int s,w,k,a[10005],b[10005];
struct BG{
int c[5005];
BG(){
memset(c,0x3f,sizeof(c));
c[0]=0;
}
void clear(){
memset(c,0x3f,sizeof(c));
c[0]=0;
}
void update(int x,int y){
for(int i=w;i>=x;i--)c[i]=min(c[i],c[i-x]+y);
}
bool friend operator+(BG a,BG b){
for(int i=0;i<=w;i++)if(a.c[i]+b.c[w-i]<=k)return true;
return false;
}
}dp[10005];
struct Q{
int top1,top2,st1[10005],st2[10005];
void push(int x){
if(!top2)st2[++top2]=x,dp[x].update(a[x],b[x]);
else {
dp[x]=dp[st2[top2]];
dp[x].update(a[x],b[x]);
st2[++top2]=x;
}
}
void pop(){
if(top1){
top1--;
return;
}
while(top2){
if(!top1){
st1[++top1]=st2[top2];
dp[st2[top2]].clear();
dp[st2[top2]].update(a[st2[top2]],b[st2[top2]]);
}
else {
dp[st2[top2]]=dp[st1[top1]];
dp[st2[top2]].update(a[st2[top2]],b[st2[top2]]);
st1[++top1]=st2[top2];
}
top2--;
}
top1--;
}
bool check(){
if(!top2)return dp[st1[top1]].c[w]<=k;
if(!top1)return dp[st2[top2]].c[w]<=k;
return dp[st1[top1]]+dp[st2[top2]];
}
}q;
signed main(){
cin>>s>>w>>k;
for(int i=1;i<=s;i++)cin>>a[i]>>b[i];
int ans=1e9;
int l=0;
for(int i=1;i<=s;i++){
q.push(i);
while(q.check())q.pop(),l++;
if(l)ans=min(ans,i-l+1);
}
if(ans>s)cout<<-1;
else cout<<ans;
return 0;
}
用双栈模拟队列的思路进行dp,因为是队列,需要有加入和删除操作,也可以想到使用双栈模拟队列的方式
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){
char c=getchar();int x=0;bool f=0;
while(c>'9'||c<'0'){
if(c=='-')f=1;
c=getchar();
}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)return -x;
return x;
}
int n,q,id;
char op[10],s[100005][25];
const int mod=998244353;
int p1[100005],top1,p2[100005],top2,dp[2][100005][21][21];
signed main(){
freopen("chess.in","r",stdin);
freopen("chess.out","w",stdout);
n=read(),q=read();
int head=1,tail=0,mid=0;
while(q--){
scanf("%s",op);
if(op[0]=='A'){
tail++;
scanf("%s",s[tail]+1);
if(head==tail){
mid=tail;
memset(dp[0][mid],0,sizeof(dp[0][mid]));
memset(dp[1][mid],0,sizeof(dp[1][mid]));
for(int i=1;i<=n;i++)dp[0][mid][i][i]=1;
}
else if(tail==mid+1)for(int i=1;i<=n;i++)dp[0][tail][i][i]=1;
else {
if(tail==mid+2)for(int i=1;i<=n;i++)dp[1][tail][i][i]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(tail-1>mid){
if(j<=n-2){
dp[0][tail][i][j]=(dp[0][tail][i][j]+dp[0][tail-1][i][j+2])%mod;
dp[1][tail][i][j]=(dp[1][tail][i][j]+dp[1][tail-1][i][j+2])%mod;
}
if(j>2){
dp[0][tail][i][j]=(dp[0][tail][i][j]+dp[0][tail-1][i][j-2])%mod;
dp[1][tail][i][j]=(dp[1][tail][i][j]+dp[1][tail-1][i][j-2])%mod;
}
}
if(tail-2>mid){
if(j<=n-1){
dp[0][tail][i][j]=(dp[0][tail][i][j]+dp[0][tail-2][i][j+1])%mod;
dp[1][tail][i][j]=(dp[1][tail][i][j]+dp[1][tail-2][i][j+1])%mod;
}
if(j>1){
dp[0][tail][i][j]=(dp[0][tail][i][j]+dp[0][tail-2][i][j-1])%mod;
dp[1][tail][i][j]=(dp[1][tail][i][j]+dp[1][tail-2][i][j-1])%mod;
}
}
}
}
}
for(int i=1;i<=n;i++)if(s[tail][i]=='#')for(int j=1;j<=n;j++)dp[1][tail][j][i]=dp[0][tail][j][i]=0;
}
else if(op[0]=='D'){
head++;
if(head>mid&&head<=tail){
mid=tail;
for(int i=head;i<=tail;i++){
memset(dp[0][i],0,sizeof(dp[0][i]));
memset(dp[1][i],0,sizeof(dp[1][i]));
}
for(int i=1;i<=n;i++)dp[0][tail][i][i]=dp[1][tail-1][i][i]=1;
for(int i=tail;i>=head;i--){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
if(i+1<=tail){
if(k+2<=n){
dp[0][i][j][k]=(dp[0][i][j][k]+dp[0][i+1][j][k+2])%mod;
dp[1][i][j][k]=(dp[1][i][j][k]+dp[1][i+1][j][k+2])%mod;
}
if(k>2){
dp[0][i][j][k]=(dp[0][i][j][k]+dp[0][i+1][j][k-2])%mod;
dp[1][i][j][k]=(dp[1][i][j][k]+dp[1][i+1][j][k-2])%mod;
}
}
if(i+2<=tail){
if(k+1<=n){
dp[0][i][j][k]=(dp[0][i][j][k]+dp[0][i+2][j][k+1])%mod;
dp[1][i][j][k]=(dp[1][i][j][k]+dp[1][i+2][j][k+1])%mod;
}
if(k>1){
dp[0][i][j][k]=(dp[0][i][j][k]+dp[0][i+2][j][k-1])%mod;
dp[1][i][j][k]=(dp[1][i][j][k]+dp[1][i+2][j][k-1])%mod;
}
}
}
}
for(int j=1;j<=n;j++)if(s[i][j]=='#')for(int k=1;k<=n;k++)dp[0][i][k][j]=dp[1][i][k][j]=0;
}
}
}
else {
int x=read(),y=read();
if(head>tail)puts("0");
else if(tail==mid)printf("%lld\n",dp[0][head][y][x]);
else {
int ans=0;
for(int i=1;i<=n;i++){
if(i+2<=n)ans=(ans+dp[0][head][i][x]*dp[0][tail][i+2][y])%mod;
if(i>2)ans=(ans+dp[0][head][i][x]*dp[0][tail][i-2][y])%mod;
if(i+1<=n){
ans=(ans+dp[0][head][i][x]*dp[1][tail][i+1][y])%mod;
ans=(ans+dp[1][head][i][x]*dp[0][tail][i+1][y])%mod;
}
if(i>1){
ans=(ans+dp[1][head][i][x]*dp[0][tail][i-1][y])%mod;
ans=(ans+dp[0][head][i][x]*dp[1][tail][i-1][y])%mod;
}
}
printf("%lld\n",ans);
}
}
}
return 0;
}

浙公网安备 33010602011771号