codefores2100-2400题解
815div.2 D2
给定一个长为n的数组a,序号从零开始。求最长的递增序号序列b,要求序列相邻元素$ a_{b_p}⊕b_{p+1}<a_{b_{p+1}}⊕b_p $
n<=3e5,0<=ai<=1e9
先可以推出一个dp公式 $ f[i] = \max \limits_{0<=j<i,a_j⊕i<a_i⊕j}(f[j]+1)\(。 简单版时,ai<=200。因为\)a-b<=a⊕b<=a+b\(。所以\)f[i]\(只需枚举\)max(1,i-400)<=j<i\(。 观察式子可得,当某一位\)a_j⊕i=a_i⊕j\(,\)a_j⊕j=a_i⊕i\(也成立。 不难发现,可以用01trie树来维护前k位数相同时,第k+1位\)a_j⊕j!=a_i⊕i且a_i⊕j=1\(的最大\)f[j]$
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T &x){
x=0;T fl=1;char tmp=getchar();
while(tmp<'0'||tmp>'9')fl=tmp=='-'?-fl:fl,tmp=getchar();
while(tmp>='0'&&tmp<='9')x=(x<<3)+(x<<1)+tmp-'0',tmp=getchar();
x=x*fl;
}
const int maxn=3e5+1000;
const int maxlog=30;
int a[maxn];
int nodes[maxn*maxlog][2];
int nodev[maxn*maxlog][2];
int n,clk;
inline int f(){
nodes[clk][0]=nodes[clk][1]=0;
nodev[clk][0]=nodev[clk][1]=0;
return clk++;
}
signed main(){
int T;cin>>T;
while(T--){
cin>>n;
for(int i=0;i<n;i++)
read(a[i]);
int ans=0;clk=0;
f();
for(int i=0;i<n;i++){
int u=0,val=a[i]^i,pos=i,getmax=0;
for(int j=maxlog;j>=0;j--){
if(nodes[u][((val>>j)&1)^1])getmax=max(getmax,nodev[nodes[u][((val>>j)&1)^1]][(((val^pos)>>j)&1)^1]);
if(!nodes[u][(val>>j)&1])break;
u=nodes[u][(val>>j)&1];
}
ans=max(ans,getmax+1);
u=0;int d=getmax+1;
for(int j=maxlog;j>=0;j--){
if(!nodes[u][(val>>j)&1])nodes[u][(val>>j)&1]=f();
u=nodes[u][(val>>j)&1];
nodev[u][(pos>>j)&1]=max(nodev[u][(pos>>j)&1],d);
}
}
cout<<ans<<endl;
}
return 0;
}
814div.1 C
给一个长为n的序列a,可以从中选取任意一个点s出发,每次固定右移k位(1<=k<n,n右侧为1)。一共移动n次,每次移动前都累计一次当前位ai的值。
对序列a共有q次单点修改。求初始状态和修改后改变s和k能得到的最大值。
n,q<=2e5,ai<=1e9
不难证明(s,k)求得的值,等价于(s,gcd(n,k))。k只需要考虑n的真因子,s为[0,k-1]的整数。
如此,最多有\(n\sqrt n\)种情况,每次修改只会修改取模后相同s的\(\sqrt n\)种情况。用multiset维护最大值。
时间复杂度\(O(n\sqrt n log(n \sqrt n))\)。略大于可容忍复杂度。
再观察发现,周期为T的环可以由周期为其因数的环组成,且答案为其平均值,显然不优于构成的小环中的最大值。如此不断递归,发现只用考虑周期为质因数的环。
当n=2e5时质因子个数不大于6。时间复杂度化为\(O(6*nlogn)\)
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T &x){
x=0;T fl=1;char tmp=getchar();
while(tmp<'0'||tmp>'9')fl=tmp=='-'?-fl:fl,tmp=getchar();
while(tmp>='0'&&tmp<='9')x=(x<<3)+(x<<1)+tmp-'0',tmp=getchar();
x=x*fl;
}
const int maxn=2e5+100;
const ll inf=1LL<<60;
ll a[maxn];
int fac[1000],cnt;
vector<ll>v[1000];
multiset<ll>hp;
int n,q;
int fl[maxn];
int prime[maxn],cntp;
void init(){
for(int i=2;i<maxn;i++){
if(!fl[i])prime[++cntp]=i,fl[i]=i;
for(int j=1;j<=cntp&&i*prime[j]<maxn;j++){
fl[i*prime[j]]=prime[j];
if(i%prime[j]==0)break;
}
}
return;
}
signed main(){
init();
int T;cin>>T;
while(T--){
read(n),read(q);
for(int i=1;i<=n;i++)
read(a[i]);
cnt=1;fac[1]=1;
int x=n;
while(x>1){
int prime=fl[x];
fac[++cnt]=n/prime;
while(x%prime==0)x/=prime;
}
sort(fac+1,fac+cnt+1);
hp.clear();hp.insert(inf);
for(int i=1;i<=cnt;i++){
int j=fac[i];
v[i].clear();
ll res;
for(int k=0;k<j;k++){
res=0;
for(int l=k;l<=n;l+=j)
res+=a[l];
res*=j;
v[i].emplace_back(res);
hp.insert(res);
}
}
printf("%lld\n",*(--hp.find(inf)));
while(q--){
ll p,x,ch;read(p),read(x);
ch=x-a[p],a[p]=x;
for(int i=1;i<=cnt;i++){
int j=fac[i],k=p%j;
hp.erase(hp.find(v[i][k]));
v[i][k]+=ch*j;
hp.insert(v[i][k]);
}
printf("%lld\n",*(--hp.find(inf)));
}
}
return 0;
}

浙公网安备 33010602011771号