D. Co-growing Sequence
题意:
给定一个数组a,要求输出一个数组b,使a^b得到的数组,ai&ai-1=ai-1。
主要思路:
本题为一个位运算的思维数学题。
经过找规律可得:
a^b&ai-1=ai-1
即 b=~a&ai-1
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e5+10;
typedef long long ll;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
ll a[N];
for(int i=0;i<n;i++)
cin>>a[i];
cout<<0<<' ';
for(int i=1;i<n;i++)
{
ll ans=a[i-1]&(-a[i]-1);
//cout<<a[i-1]<<' '<<(-a[i])<<' '<<ans<<endl;
cout<<ans<<' ';
a[i]=a[i]^ans;
}
cout<<endl;
}
return 0;
}
E. Air Conditioners
题意:
一共n个位置,存在k个位置有雪花,离雪花远一格就热一度,输出每个位置的最低温度。
主要思路:
这个问题是一个边界扩散问题,分别从左右两个边界扩散,去最小值即可。
!!!注意初始化的值尽量大
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int N=3e5+10,maxa=11e9+10;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k;
cin>>n>>k;
ll l[N]={0},r[N]={0},w[N];
map<ll,ll>v;
for(int i=0;i<k;i++)
cin>>w[i];
for(int i=0;i<=n;i++)
v[i]=maxa;
for(int j=0;j<k;j++)
{
ll x;
cin>>x;
v[w[j]]=x;
}
ll p=maxa;
for(int i=0;i<n;i++)
{
p=min(p+1,v[i+1]);
l[i]=p;
}
p=maxa;
for(int i=n-1;i>=0;i--)
{
p=min(p+1,v[i+1]);
r[i]=p;
}
for(int i=0;i<n;i++)
{
ll ans=min(l[i],r[i]);
cout<<ans<<' ';
}
cout<<endl;
}
return 0;
}
F. Array Stabilization (GCD version)
题意:
给定一个数组a,进行ai=gcd(ai,ai+1)的操作,问经过几轮操作后,a中的数相同?
主要思路:
首先将题目进行变形,认真分析可以发现,经过x次操作,即将i处的值a[i]变为gcd(a[i]~a[i+x])。
因为这题给了4s的时间,所以暴力也可以过,推荐二分优化。
暴力:
分别以1-n为起点,计算最少经过多少次,使该位置的数值不再改变(即所有位置的值都相同了)。
二分:
分析可知,最多进行n-1次操作即可将所有元素统一。可以二分mid=(1+n-1)/2。用树状数组或ST表查询各个区间的最大公约数,若相同则r=mid,否则l=mid+1。
(还没学树状数组查询最大公约数,学完补上)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e5+10;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
int a[N];
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
int ans=0;
for(int i=0;i<n;i++)
{
int sum=0;
int x=a[i],y=a[(i+1)%n],s=i+1;
while(x!=y)//还需要进行下一轮
{
x=__gcd(x,a[s%n]);
y=__gcd(y,a[(s+1)%n]);
s++;
sum++;
}
ans=max(ans,sum);
}
cout<<ans<<endl;
}
return 0;
}
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=4e5+10;
int f[N][40];
int a[N];
int n;
void init()
{
int k=floor(log((double)(2*n))/log(2.0));
for(int j=1;j<=k;j++)
{
for(int i = 1; i + (1 << j) - 1 <= n + n; i++)
f[i][j]=__gcd(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
int query(int l,int r)
{
int k=floor(log((double)(r-l+1))/log(2.0));
return __gcd(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
for(int i = 1; i <= n; i++)
cin >> a[i];
for(int i = 1; i <= n; i++) a[i + n] = a[i], f[i][0] =f[i + n][0] = a[i];
int g=a[1];
for(int i=2;i<=n;i++)
g=__gcd(g,a[i]);
init();
int ans=0;
for(int i=1;i<=n;i++)
{
int l=i,r=i+n-1;
while(l<r)
{
int mid=(l+r)>>1;
if(query(i,mid)==g)
r=mid;
else l=mid+1;
}
ans=max(ans,l-i);
}
cout<<ans<<endl;
}
return 0;
}