序列更新
给定两个长度为n 的序列$ 𝑎_0,𝑎_1,…,𝑎_{𝑛−1}$ 和
你需要依次执行q次操作,每次操作将会给出一个整数,对于每个$ 𝑖 (0≤𝑖<𝑛)$,你需要将 更新为 为了证明你确实维护了a序列,请在每次操作之后输出 $\sum_{i=0}^{i<n}a_i $的值。
第一行包含一个正整数 ,表示测试数据的组数。
每组数据第一行包含两个正整数$ 𝑛,𝑞 (1≤𝑛,𝑞≤250,000)$,分别表示序列的长度以及操作的次数。
第二行包含 $𝑛 $个正整数 。
第三行包含 个正整数
接下来 𝑞行,每行一个整数 𝑘 (0≤𝑘<𝑛),依次描述每次操作。
输入数据保证每个 𝑎𝑖,𝑏𝑖 都是在 均匀随机生成得到(样例除外),且每个 k 都是在 均匀随机生成得到(样例除外)。
对于每组数据输出 𝑞 行,其中第 𝑖 行输出一个整数,即在第 𝑖 次操作完毕之后 的值。
1 5 5 1 5 3 6 8 2 5 4 7 3 3 2 4 1 0
29 31 33 35 36
:
常规考虑基本都是无解。唯一指向性的线索就是只会单调递增以及都是均匀随机生成。
考虑在之间设置一个阙值:
当,对于每个都依次去用尝试更新,直到大于。
当,则存起来,后用去更新
对于第二种期望次数为设为x次(即有x个数大于S)
对于第一种:即为连续次每个数都不超过的概率为让的期望次数
原式为
上式两边同时得:
正无穷小,原式由等比数列求和化简可得:,其中1可以忽略不计只需要保证即可
总时间复杂度为
当时即时间复杂度最优为
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define int long long
#define PII pair<int, int>
#define PI acos(-1)
#define s second
#define f first
#define Bint __int128
#define all(x) x.begin(),x.end()
#define isdigit(x) ((x) >= '0' && (x) <= '9')
#define double long double
#define ULL unsigned long long
const int N = 2e5 + 7, P = 998244353;
const int M = 1e6 + 7, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
int n,q,a[N],b[N],c[N],A[N],B[N],ca,cb,sum;
inline void fix(int&x){
while(x<=0)x+=n;
while(x>n)x-=n;
}
inline void modify(int x,int y){
fix(x);
fix(y);
if(a[x]>=b[y])return ;
sum+=b[y]-a[x];
a[x]=b[y];
}
void solve(){
ca=0,cb=0;
cin>>n>>q;
sum=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i],c[i]=b[i];
int s=sqrt(n);
s=max(s,(int)1);
sort(c+1,c+1+n);
for(int i=1;i<=n;i++){
sum+=a[i];
if(a[i]<=s)A[ca++]=i;
if(b[i]>s)B[cb++]=i;
}
while(q--){
int k;cin>>k;
for(int i=0;i<ca;){
modify(A[i],A[i]+k);
if(a[A[i]]>s)swap(A[i],A[--ca]);else i++;
}
for(int i=0;i<cb;i++){
modify(B[i]-k,B[i]);
}
}
return ;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
最优 K 子段
分析:
首先对最小值二分答案。那么在中贪心维护最小值的最多子段数量。
从左端点开始枚举,通过维护一个前缀去保证以位置结尾的子段可以
那么对于每一个暴力枚举中的元素满足为质数的时间复杂度为多少?
因为起初数组元素是均匀分布,那么其也满足均匀分布,那么其位置也满足均匀分布
因为的质数个数,为质数概率,期望为
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define int long long
#define PII pair<int, int>
#define PI acos(-1)
#define s second
#define f first
#define Bint __int128
#define all(x) x.begin(),x.end()
#define isdigit(x) ((x) >= '0' && (x) <= '9')
#define double long double
#define ULL unsigned long long
const int N = 2e5 + 7, P = 998244353;
const int M = 1e6 + 7, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-6;
int n,a[N],k,pre[N];
int primes[1000009],cnt;
bool st[1000009];
set<PII>b;
void get_primes(int n)
{
st[1]=1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
bool check(int x){
b.clear();
b.insert(PII{0,0});
int res=0;
for(int i=1;i<=n;i++){
int s=pre[i];
if(pre[i]-b.begin()->f>=x){
bool f=0;
for(auto &[p,pos]:b){
if(s-p>=x&&!st[i-pos]){
f=1;
break;
}
else if(s-p<x)break;
}
if(f){
res++;
b.clear();
if(res==k)return 1;
}
}
b.insert(PII{pre[i],i});
}
return 0;
}
void solve(){
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i],pre[i]=a[i]+pre[i-1];
int l=0,r=0;
for(int i=1;i<=n;i++)
if(a[i]>=0)r+=a[i];
else l+=a[i];
while(l<r){
int mid=l+r+1>>1;
if(check(mid))l=mid;
else r=mid-1;
}
if(check(l))
cout<<l<<"\n";
else cout<<"impossible\n";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}