暑假集训csp提高模拟3

赛时 rank 20,T1 0,T2 45,T3 20,T4 95

T1粘了两遍(因为OJ卡第一次没有显示出来)CE了,挂了100,T4没卡常挂了5

汤碗了!!!!!!!!!!!!!!!

T1 abc猜想

对于任意整数c都有

ab+c=ab+c=a+bcb

所以

abc=kc+ans

ans=abkc2c=abmodc2c

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
ll a,b,c;
inline ll power(ll a,ll b,ll mod){
ll res = 1;
while(b){
if(b & 1) res = res * a % mod;
b >>= 1;
a = a*a%mod;
}
return res;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
cin>>a>>b>>c;
cout<<power(a,b,c*c)/c<<'\n';
}

死亡回放

image

image

T2 简单的排列最优化题

O(n)做法

将排列中的数分为两类,πi>iπii

记第一类的总数为zcnt,贡献为ztot

记第二类的总数为fcnt,贡献为ftot

除了放到队首的数,第一类数做出的贡献和减掉zcnt,第二类数做出的贡献和加上fcnt

当一个数从第一类数变为第二类数时,那么有πii=0,预处理每个数变化的时间即可。

第二类数变成第一类数时,只能是是队尾变队首,特判。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
const int N = 1e7 + 10;
int n,zcnt,fcnt,a[N],Z[N];
ll ztot,ftot;
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
cin>>n;
for(int i = 1;i <= n; ++i) cin>>a[i];
for(int i = 1;i <= n; ++i){
if(a[i] <= i) fcnt++,ftot += i-a[i];
else zcnt++,ztot+=a[i]-i,Z[a[i]-i]++;
}
ll ans = ztot+ftot,id = 0;
for(int i = 1;i < n; ++i){
ztot -= zcnt;
zcnt -= Z[i];
ftot += fcnt;
fcnt += Z[i];
int x = a[n - i + 1];
ftot -= n+1-x,--fcnt;
if(x > 1) Z[x-1+i]++,ztot+= x-1,++zcnt;
else ++fcnt;
if(ans > ftot + ztot) ans = ftot+ztot,id = i;
}
cout<<ans<<' '<<id<<'\n';
}

T3 简单的线性做法题

小清新的分治做法

区间[lr]的绝对众数x(即出现次数大于len2的众数)满足对于任意的lkr,x一定为区间[lk](kr]的绝对众数。利用这一性质分治,O(n)从mid出发扫描能够成为众数的数。

枚举众数x,求当前区间中的满足绝对众数为x的子区间个数。

先从mid开始向左扫描左端点b,记录midb+1cntx不同取值的个数。
再向右扫描右端点e,求满足eb+1cntx>eb+12[be]个数。

时间复杂度O(nlog2n)

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
const int N = 5e5 + 10;
int n,a[N],pos[N],num[N],cnt[N*2];
ll ans;
void solve(int l,int r){
if(l == r) {ans++;return;}
int mid = (l+r)>>1;
solve(l,mid);solve(mid+1,r);
for(int i = mid;i >= l;--i){
if(++cnt[a[i]] > (mid - i + 1)/2){
if(!pos[a[i]]) num[pos[a[i]] = ++num[0]] = a[i];
}
}
for(int i = mid+1;i <= r;++i){
if(++cnt[a[i]] > (i - mid)/2){
if(!pos[a[i]]) num[pos[a[i]] = ++num[0]] = a[i];
}
}
for(int i = l;i <= r; ++i) pos[a[i]] = cnt[a[i]] = 0;
for(int i = 1;i <= num[0]; ++i){
int sum = r-l+1,mx = sum,mn = sum;
cnt[sum] = 1;
for(int j = l;j < mid; ++j){
if(a[j] == num[i]) sum++;
else sum--;
mx = max(mx,sum);
mn = min(mn,sum);
cnt[sum]++;
}
if(a[mid] == num[i]) sum++;
else sum--;
for(int j = mn;j <= mx; ++j) cnt[j] += cnt[j - 1];
for(int j = mid+1;j <= r; ++j){
if(a[j] == num[i]) sum++;
else sum--;
ans += cnt[min(mx,sum-1)];
}
for(int i = mn;i <= mx; ++i) cnt[i] = 0;
}
num[0] = 0;
}
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
cin>>n;int x;cin>>x;
for(int i = 1;i <= n; ++i) cin>>a[i];
solve(1,n);
cout<<ans;
}

T4 简单的线段树题

n很大,分块无法过,线段树维护就可以了,其他的和分块一样,卡卡常数。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
const int N = 1e6 + 10;
inline void read(ll &x){
x = 0;
char s = getchar();
for(;s<'0'||s >'9';s=getchar());
for(;'0' <= s && s<='9';s=getchar()) x = (x<<1)+(x<<3)+(s^48);
}
ll n,m;ll a[N];
void write(ll x){
if(x > 9) write(x/10);
putchar(x%10+48);
}
struct Segment_Tree{
struct segment_tree{
int l,r,lazy,tot;ll sum;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
#define lazy(x) tree[x].lazy
#define tot(x) tree[x].tot
}tree[N<<2];
inline void pushup(int k){
sum(k) = sum(k<<1) + sum(k<<1|1);
tot(k) = min(tot(k<<1),tot(k<<1|1));
}
inline void pushdown(int k){
if(lazy(k)){
int ls = k<<1,rs = k<<1|1;
lazy(ls) += lazy(k);
lazy(rs) += lazy(k);
if(tot(ls) >= 6) tot(ls) = 6;
else{
tot(ls) += lazy(k);
sum(ls) = 0;
for(int i = l(ls);i <= r(ls); ++i) sum(ls) += a[i];
}
if(tot(rs) >= 6) tot(rs) = 6;
else{
tot(rs) += lazy(k);
sum(rs) = 0;
for(int i = l(rs);i <= r(rs); ++i) sum(rs) += a[i];
}
lazy(k) = 0;
}
}
void build(int k,int l,int r){
l(k) = l,r(k) = r;
if(l == r)return sum(k) = a[l],void();
int mid = (l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}
void update(int k,int l,int r){
if(tot(k) == 6) return;
if(l <= l(k) && r(k) <= r){
if(tot(k) == 6) return;
tot(k)++;lazy(k)++;
sum(k) = 0;
for(int i = l(k);i <= r(k); ++i) sum(k) += (a[i] = sqrt(a[i]));
return;
}
pushdown(k);
int mid = (l(k) + r(k))>>1;
if(l <= mid) update(k<<1,l,r);
if(r > mid) update(k<<1|1,l,r);
pushup(k);
}
ll query(int k,int l,int r){
if(l <= l(k) && r(k) <= r) return sum(k);
pushdown(k);
int mid = (l(k) + r(k))>>1;
ll res = 0;
if(l <= mid) res += query(k<<1,l,r);
if(r > mid) res += query(k<<1|1,l,r);
return res;
}
}T;
signed main(){
read(n);
for(int i = 1;i <= n; ++i) read(a[i]);
T.build(1,1,n);
read(m);
int ttt = 0;
while(m--){
ll op,l,r;
read(op),read(l),read(r);
if(op == 0) T.update(1,l,r);
else write(T.query(1,l,r)),puts("");
// if(op) ttt++;
// if(ttt == 141 && op) cerr<<l<<' '<<r<<'\n';
}
}
posted @   CuFeO4  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示