[AGC055B] ABC Supremacy
令 ABC
分別為 1,2,3,然後令 \(s_i=(s_i-i) \text mod 3\) 且結果大於 0。
然後可以發現三種組合均為連貫的三個相同數。且可以自由移動。
可以選擇每遇到三個相同數就刪掉,或者不斷加入棧,如果棧頂三個數相同全部彈出。
再比較剩下的數即可。
#include<bits/stdc++.h>
#define maxn 600100
using namespace std;
int n,cnts,cntt;
int S[maxn],T[maxn];
string a,b;
bool viss[maxn],vist[maxn];
int s[maxn],t[maxn];
stack<int> A,B;
int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
return s*w;
}
int main(){
n=read();
cin>>a>>b;
for(int i=0;i<n;i++){
if(a[i]=='A') s[i+1]=1;
if(a[i]=='B') s[i+1]=2;
if(a[i]=='C') s[i+1]=3;
if(b[i]=='A') t[i+1]=1;
if(b[i]=='B') t[i+1]=2;
if(b[i]=='C') t[i+1]=3;
s[i+1]=(s[i+1]-(i+1))%3;
t[i+1]=(t[i+1]-(i+1))%3;
if(s[i+1]<0) s[i+1]+=3;
if(t[i+1]<0) t[i+1]+=3;
}
for(int i=1;i<=n;i++){
if(A.size()>=2){
int x=A.top();A.pop();
int y=A.top();A.pop();
if(!(x==y&&x==s[i])){
A.push(y);A.push(x);
A.push(s[i]);
}
}
else A.push(s[i]);
if(B.size()>=2){
int x=B.top();B.pop();
int y=B.top();B.pop();
if(!(x==y&&x==t[i])){
B.push(y);B.push(x);
B.push(t[i]);
}
}
else B.push(t[i]);
}
if(A.size()!=B.size()){
puts("NO");return 0;
}
while(A.size()){
if(A.top()!=B.top()) {puts("NO");return 0;}
A.pop();B.pop();
}
puts("YES");
return 0;
}
BZOJ2616 SPOJ PERIODNI
題解做法,注意統計答案的順序。
#include<bits/stdc++.h>
#define maxn 1000100
#define Mod 1000000007
#define LL long long
using namespace std;
int n,k;
int a[maxn];
LL st[maxn],top;
int ls[maxn],rs[maxn],size[maxn];
LL int f[1010][1010],g[1010][1010];
LL int inv[maxn],mul1[maxn],mul2[maxn];
int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
return s*w;
}
LL int C(LL int x,LL int y){
return y>x?0:mul1[x]*mul2[y]%Mod*mul2[x-y]%Mod;
}
void dfs(int u,int fa){
if(ls[u])dfs(ls[u],u);
if(rs[u])dfs(rs[u],u);
size[u]=size[ls[u]]+size[rs[u]]+1;
for(int i=0;i<=size[ls[u]];i++){
for(int o=0;o<=size[rs[u]];o++){
g[u][i+o]+=f[ls[u]][i]*f[rs[u]][o]%Mod;
g[u][i+o]%=Mod;
}
}
for(int i=0;i<=size[u];i++){
for(int o=0;o<=i;o++){
f[u][i]+=g[u][o]*(C(size[u]-o,i-o)*C(a[u]-a[fa],i-o)%Mod*mul1[i-o]%Mod)%Mod;
f[u][i]%=Mod;
}
}
}
int main(){
n=read();k=read();
inv[0]=mul1[0]=mul2[0]=1;
inv[1]=mul1[1]=mul2[1]=1;
for(LL int i=2;i<=1e6;i++){
inv[i]=inv[Mod%i]*(Mod-Mod/i)%Mod;
mul1[i]=mul1[i-1]*i%Mod;
mul2[i]=mul2[i-1]*inv[i]%Mod;
}
for(int i=1,k;i<=n;i++){
a[i]=read();k=top;
while(k>0&&a[st[k]]>a[i])k--;
if(k)rs[st[k]]=i;
if(k<top)ls[i]=st[k+1];
st[++k]=i;top=k;
}
f[0][0]=1;
dfs(st[1],0);
cout<<f[st[1]][k];
}
ICPC2023 Macau Gym104891C
貪心想的話是能選哪種選哪種。
分塊跳跳跳,統計跳出當前塊的步數和位置。
統計一個標記來維護整個塊內部,記錄用哪一種牌。
程式碼實現借鑑了涼笙和課件 std。
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
return s*w;
}
int n,k,len,maxx;
int pos[maxn],L[maxn],R[maxn],a[maxn];
int to[maxn],nxt[maxn],f[maxn],tag[maxn],lstf[maxn];
set<int> s;
void change(int x,int val){
if(val>0)nxt[x]=val;
else nxt[x]=x+k;
}
void rebuild(int id){
for(int i=R[id];i>=L[id];i--){
if(nxt[i]>R[id]){
to[i]=nxt[i];f[i]=1;
lstf[i]=(!(i>=maxx));
}
else{
to[i]=to[nxt[i]];f[i]=f[nxt[i]]+1;
lstf[i]=(i>=maxx)?0:lstf[nxt[i]]+1;
}
}
}
void pushdown(int u){
if(!tag[u]) return;
for(int i=L[u];i<=R[u];i++)change(i,tag[u]);
tag[u]=0;
}
void update(int x,int y,int val){
if(pos[x]==pos[y]){
pushdown(pos[x]);
for(int i=x;i<=y;i++)change(i,val);
rebuild(pos[x]);
return ;
}
pushdown(pos[x]);
for(int i=x;i<=R[pos[x]];i++)change(i,val);
rebuild(pos[x]);
pushdown(pos[y]);
for(int i=L[pos[y]];i<=y;i++)change(i,val);
rebuild(pos[y]);
for(int i=pos[x]+1;i<pos[y];i++)tag[i]=val;
}
int query(int mx){
int now=0,res=0;
while(now<mx){
if(tag[pos[now]]>0)res++,now=tag[pos[now]];
else if(tag[pos[now]]==-1)res++,now+=k;
else {
if(pos[now]!=pos[mx])res+=f[now],now=to[now];
else res+=lstf[now],now=to[now];
}
}
return res;
}
int main(){
int T=read();
while(T--){
n=read();k=read();len=sqrt(n);
for(int i=1;i<=n;i++)
a[i]=read(),L[i]=R[i]=0;
for(int i=0;i<=n;i++){
pos[i]=(i-1)/len+1;
if(!L[pos[i]])L[pos[i]]=i;
R[pos[i]]=i;
nxt[i]=to[i]=n+1;
f[i]=lstf[i]=tag[i]=0;
}
pos[0]=L[0]=R[0]=0;s.insert(0);
for(int i=1;i<=n;i++){
maxx=max(maxx,a[i]);s.insert(a[i]);
int lst=*(--s.lower_bound(a[i]));
int l=max(lst,a[i]-k);update(l,a[i]-1,-1);
if(lst<a[i]-k)update(lst,a[i]-k-1,a[i]);
int ans=query(maxx);cout<<ans<<" ";
}
puts("");
maxx=0;
}
return 0;
}