没看到输出“Yes”卡了二十分钟【再见】
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 600
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m;
char mp[N][N];
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();
for(int i=1;i<=n;++i)
scanf("%s",mp[i]+1);
for(int i=1;i<=n;++i)
for(int j=1;jif((mp[i][j]=='S'&&mp[i][j+1]=='W')||(mp[i][j]=='W'&&mp[i][j+1]=='S')){puts("No");return 0;}
for(int j=1;j<=m;++j)
for(int i=1;iif((mp[i][j]=='S'&&mp[i+1][j]=='W')||(mp[i][j]=='W'&&mp[i+1][j]=='S')){puts("No");return 0;}
puts("Yes");
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j) if(mp[i][j]=='.') mp[i][j]='D';
puts(mp[i]+1);
}return 0;
}
再一次卡了半天【再见】
我们可以先O(n)处理出P(n),表示n的最大质因数。
然后我们发现 xi 的取值范围为 xi+1>=xi>xi+1−P(xi+1) 。于是我们可以枚举x1,然后O(1)得到最小的x0.
在讨论中看到,其实可以做到 O(n)+O(logn) 。
令Q(n)=n/P(n).则 x0=x1−P(x1)+1=x1(1−1/Q(x1)+1
从小到大枚举x1的话,显然当Q(x1)=2时再大的x1就不会使得x0的值就更小了。而Q(n)=2,说明n=2*P(n),而质数分布大概是log的,所以我们最多枚举log个x1就可以了。
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 1000010
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,ans=inf,tot=0,prime[N],a[N];
bool notprime[N];
void getprime(){
notprime[1]=1;
for(int i=2;i<=1000000;++i){
if(!notprime[i]) prime[++tot]=i,a[i]=i;
for(int j=1;prime[j]*i<=1000000;++j){
notprime[prime[j]*i]=1;a[prime[j]*i]=a[i];
if(i%prime[j]==0) break;
}
}
}
int main(){
// freopen("a.in","r",stdin);
int n=read(),x=n,mx=0;getprime();
for(int i=2;i*i<=n;++i){
if(x%i) continue;
while(x%i==0) x/=i;
mx=i;
}if(x!=1) mx=x;
for(int i=n-mx+1;i<=n;++i){
if(!notprime[i]) continue;
ans=min(ans,i-a[i]+1);
}printf("%d\n",ans);
return 0;
}
大概就是给t数组做个前缀和,然后二分一下这堆雪在那一天化没,记录对答案的贡献。Visjiao巨佬用splay直接踩了过去。
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,a[N],t[N],c[N];
ll sum[N],ans[N];
inline void add(int x,int val){
for(;x<=n;x+=x&-x) c[x]+=val;
}
inline int ask(int x){
int res=0;for(;x;x-=x&-x) res+=c[x];return res;
}
int main(){
// freopen("a.in","r",stdin);
n=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i) t[i]=read(),sum[i]=sum[i-1]+t[i];
for(int i=1;i<=n;++i){
ll x=a[i]+sum[i-1];
int cnt=upper_bound(sum+1,sum+n+1,x)-sum;//i~cnt-1
if(i!=cnt) add(i,1),add(cnt,-1);
ans[cnt]+=x-sum[cnt-1];
}for(int i=1;i<=n;++i) printf("%I64d ",ans[i]+(ll)ask(i)*t[i]);
return 0;
}
复杂度 O(nlogw)
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 300010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,a[N],son[N*30][2],cnt[N*30],bin[32],rt=1,tot=1,ans;
inline void ins(int x){
int p=rt;cnt[rt]++;
for(int i=29;i>=0;--i){
int op=x>>i&1;
if(!son[p][op]) son[p][op]=++tot;p=son[p][op];
cnt[p]++;
}
}
inline void ask(int x){
int p=rt;
for(int i=29;i>=0;--i){
int op=x>>i&1;
if(!son[p][op]||!cnt[son[p][op]]) ans|=bin[i],p=son[p][op^1];
else p=son[p][op];cnt[p]--;
}
}
int main(){
// freopen("a.in","r",stdin);
n=read();bin[0]=1;
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=30;++i) bin[i]=bin[i-1]<<1;
for(int i=1;i<=n;++i){
int x=read();ins(x);
}for(int i=1;i<=n;++i){
ans=0;ask(a[i]);printf("%d ",ans);
}return 0;
}
通过手玩发现B和C可以互换,于是把C都换成B。然后我们的操作就是
A->BB
AB->B
B->AB
AAA->empty string
于是一个B的前面我们可以加减若干A,于是我们只需考虑B的个数以及末尾A的个数。
分三类:
1、末尾A个数相等,B1>B2且差为偶数则ok
2、原串有B,A1>A2,则(A1-A2)%3若还剩,就需要换出一个BB,然后转1
3、原串无B,则A1必须大于A2,并换出一个BB。
赛后A题gg(赛后也fst呢【逃】)
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m,sum1[N],sum2[N],Q,la1[N],la2[N];
char s1[N],s2[N],ans[N];
int main(){
// freopen("a.in","r",stdin);
scanf("%s",s1+1);scanf("%s",s2+1);
n=strlen(s1+1);m=strlen(s2+1);Q=read();
for(int i=1;i<=n;++i){
sum1[i]=sum1[i-1]+(s1[i]!='A');
if(s1[i]=='A') la1[i]=la1[i-1]+1;else la1[i]=0;
}
for(int i=1;i<=m;++i){
sum2[i]=sum2[i-1]+(s2[i]!='A');
if(s2[i]=='A') la2[i]=la2[i-1]+1;else la2[i]=0;
}
for(int i=1;i<=Q;++i){
int l1=read(),r1=read(),l2=read(),r2=read();
int cnt1=sum1[r1]-sum1[l1-1],cnt2=sum2[r2]-sum2[l2-1];
int num1=min(la1[r1],r1-l1+1),num2=min(la2[r2],r2-l2+1);
if(num1'0';continue;}
if(!cnt1&&cnt2){
if(num1==num2){ans[i]='0';continue;}
cnt1+=2;
}
else if((num1-num2)%3) cnt1+=2;
if(cnt1>cnt2||(cnt2-cnt1)&1) {ans[i]='0';continue;}
ans[i]='1';
}puts(ans+1);
return 0;
}
总结:反向做题简直日神仙。