AtCoder Beginner Contest 368 补题记录(A~D,F,G)
被伟大的 G 创似辣。
A
signed main(){
int n,k;cin>>n>>k;
F(i,1,n)cin>>a[i];
queue<int>stk;
G(i,n,1)stk.push(a[i]);
while(k--){
int t=stk.front();
stk.push(t);
stk.pop();
}
stack<int>t;
F(i,1,n){
t.push(stk.front());
stk.pop();
}
while(t.size()){
cout<<t.top()<<' ';
t.pop();
}
cout<<'\n';
return 0;
}
B
const int N=1000100;
int a[N];
signed main(){
int n,k;cin>>n;
F(i,1,n)cin>>a[i];
int cnt=0;
VI t;
F(i,1,n)t.eb(a[i]);
while(true){
if(t.size()<2)break;
sort(rng(t),greater<>());
--t[0],--t[1];
VI nw;
for(auto &x:t)
if(x>0)nw.eb(x);
t.swap(nw);
// cout<<"qwq: ";
// for(auto &x:t)cout<<x<<' ';
// cout<<'\n';
++cnt;
}
cout<<cnt<<'\n';
return 0;
}
C
容易发现攻击 \(3\) 次一循环,一共对怪物攻击 \(5\) 次。所以对于 \(a_i\ge 5\) 的部分直接算,\(a_i<5\) 的部分暴力模拟。
时间复杂度为 \(O(n)\)。
const int N=1000100;
int a[N];
signed main(){
int n;cin>>n;
F(i,1,n)cin>>a[i];
int cnt=0;
F(i,1,n){
cnt+=a[i]/5*3;
a[i]%=5;
while(a[i]>0){
++cnt;
if(cnt%3==0)a[i]-=3;
else --a[i];
}
}
cout<<cnt<<'\n';
return 0;
}
D
这让我想起了昨天做过的某道树剖。考虑在 \(a\) 中随机钦定一个结点为根,然后以这个点为根重构整棵树。枚举 \(a\) 中每一个点,将 \(a\) 到根的简单路径上每一个点都打一个标记。最后询问总共有多少个标记即可。
这个东西可以用树剖套线段树(或者 ODT)维护,维护当前区间内总共被打了多少个标记,然后再上一个懒标记即可,但是因为树剖没有复制板子导致吃 \(3\) 发罚时。
因此总时间复杂度为 \(O(n\log^2n)\)。
const int N=600100;
int n,m,s;
VI z[N];
int sz[N],dep[N],hev[N],top[N],up[N],dfn[N],back[N],a[N],xia[N];
void dfs(int u,int fa){
sz[u]=1,dep[u]=dep[fa]+1,up[u]=fa;
for(auto &v:z[u])if(v!=fa){
dfs(v,u),sz[u]+=sz[v];
xia[u]=v;
if(sz[hev[u]]<sz[v])hev[u]=v;
}
}
int idx;
void dfs2(int u,int Top,int fa){
top[u]=Top;
dfn[u]=++idx,back[idx]=u;
if(hev[u])dfs2(hev[u],Top,u);
for(auto &v:z[u])if(v!=fa&&v!=hev[u])
dfs2(v,v,u);
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]])
u=up[top[u]];
else
v=up[top[v]];
}
if(dep[u]<dep[v])
return u;
return v;
}
namespace yhb{
struct qwq{
int l,r,sum,tag;
void init(int p){
l=r=p;sum=0;
tag=0;
}
void yhb(int v){
sum=(r-l+1)*v;
tag=v;
}
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){ //pushup
return {l.l,r.r,l.sum+r.sum,0ll};
}
void build(int l,int r,int rt){
if(l==r)return z[rt].init(l);
int mid=l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){ //pushdown
if(z[rt].tag){
z[rt<<1].yhb(z[rt].tag);
z[rt<<1|1].yhb(z[rt].tag);
z[rt].tag=0;
}
}
void modify(int l,int r,int rt,int ll,int rr,int v){
if(ll<=l&&r<=rr){z[rt].yhb(v);return;}
int mid=l+r>>1;pushyhb(rt);
if(ll<=mid)modify(l,mid,rt<<1,ll,rr,v);
if(mid<rr)modify(mid+1,r,rt<<1|1,ll,rr,v);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query(int l,int r,int rt,int ll,int rr){
if(ll<=l&&r<=rr)return z[rt].sum;
int mid=l+r>>1,s=0;pushyhb(rt);
if(ll<=mid&&mid<rr)return query(l,mid,rt<<1,ll,rr)+query(mid+1,r,rt<<1|1,ll,rr);
if(mid<rr)return query(mid+1,r,rt<<1|1,ll,rr);
return query(l,mid,rt<<1,ll,rr);
}
}
void lnk_modify(int u,int v,int w){
while(top[u]!=top[v]){
if(dep[up[top[u]]]<dep[up[top[v]]])
swap(u,v);
yhb::modify(1,n,1,dfn[top[u]],dfn[u],w);
u=up[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
yhb::modify(1,n,1,dfn[u],dfn[v],w);
}
int lnk_query(int u,int v){
int s=0;
while(top[u]!=top[v]){
if(dep[up[top[u]]]<dep[up[top[v]]])
swap(u,v);
s+=yhb::query(1,n,1,dfn[top[u]],dfn[u]);
u=up[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
s+=yhb::query(1,n,1,dfn[u],dfn[v]);
return s;
}
#ifndef THIS_IS_JIAOHUTI
signed main(){
// freopen("count_in","r",stdin);freopen("count.out","w",stdout);
ios_base::sync_with_stdio(0);cin.tie(0);
int k;
cin>>n>>k;F(i,1,n-1){
int u,v;cin>>u>>v;
Adde(u,v);
}
F(i,1,k)cin>>a[i];
dfs(a[1],0),dfs2(a[1],a[1],0);
yhb::build(1,n,1);
F(i,1,k)lnk_modify(a[1],a[i],1);
cout<<yhb::z[1].sum<<'\n';
}
E
咕咕咕。
F
每一个游戏之间互相独立,所以考虑求解每一个游戏的 SG 值。
对每一个 SG 值做一次记忆化 dp:
- 若 \(x=1\),则 \(\text{SG}(x)=0\)。
- 否则,\(\forall\ d\ s.t.\ d\mid x\),令 \(F\leftarrow x\),则 \(\text{SG}(x)=\text{Mex}(F)\)。
求所有满足条件的 \(d\) 可以 Pollard-Rho 然后暴力重构做到大概是 \(O(n^\frac{4}{5}+n\ln^2n)\),但是我懒所以直接暴力分解质因数,做到了 \(O(n^\frac{3}{2})\)。
const int N=600100;
int sg[N];
int SG(int x){
if(~sg[x])return sg[x];
VI t;
for(int i=1;i*i<=x;++i){
if(x%i==0&&i!=x)t.eb(SG(i));
if(x%i==0&&i*i!=x&&x/i!=x)t.eb(SG(x/i));
}
unordered_set<int>se;
for(auto &x:t)se.insert(x);
F(i,0,1e18)if(!se.count(i)){
return sg[x]=i;
}
return -1;
}
#ifndef THIS_IS_JIAOHUTI
signed main(){
// freopen("count_in","r",stdin);freopen("count.out","w",stdout);
// ios_base::sync_with_stdio(0);cin.tie(0);
int n;cin>>n;
int xr=0;
FIN(sg);
F(i,1,100000){
// if(i%1000==0)cout<<i<<'\n';
SG(i);
}
F(i,1,n){
int x;cin>>x;
xr^=sg[x];
}
if(xr)cout<<"Anna\n";
else cout<<"Bruno\n";
}
#else
#define NO_MAIN
void no_main() {
puts("pwp");
}
#endif
G
首先考虑维护一大堆线段树分别维护:
- 每个元素最左边的 \(1\) 位置 \(i_1\)。
- 每个元素最右边的 \(1\) 位置 \(i_2\)。
- 每一段区间的和 \(i_3\)。
- 每一段区间的最大 \(b\) 值 \(i_4\)。
- 每一段区间 \(b\) 值的最大位置 \(i_5\)。
然后可以使用 \(4\) 个线段树来维护上述的所有信息。时间复杂度为 \(O(n)\)。
维护完之后可以发现暴力时间复杂度正确:因为选择乘法的次数不会超过 \(\log_2 10^{18}\approx 60\),因此把所有连续 \(1\) 块暴力缩之后最多只会枚举 \(120\) 个元素。因此总的时间复杂度是 \(O(n\log n\log V)\),其中 \(V\) 是值域。
说的有点混乱,建议结合代码查看。
#
/*
#define THIS_IS_JIAOHUTI
*/
#
#include<bits/stdc++.h>
#define pb push_back
#define eb emplace_back
#ifndef THIS_IS_JIAOHUTI
#define int long long
#endif
#define F(i,x,y) for(int i=x;i<=y;++i)
#define G(i,x,y) for(int i=x;i>=y;--i)
#define FD(x,y) for(int i=x;i*i<=y;++i)
#define GD(x,y) for(int i=x;i*i>=y;--i)
#define adde(x,y) z[x].eb(y);
#define Adde(x,y) z[x].eb(y),z[y].eb(x);
#define addew(x,y,w) z[x].eb(y,w)
#define Addew(x,y,w) z[x].eb(y,w),z[y].eb(x,w)
#define FIMX(X) memset(X,0x3f,sizeof X)
#define FIMI(X) memset(X,-0x3f,sizeof X)
#define FI0(X) memset(X,0,sizeof X)
#define FIN(X) memset(X,-1,sizeof X)
#define rng(X) X.begin(),X.end()
#define PII pair<int,int>
#define PDD pair<double,double>
#define PIII tuple<int,int,int>
#define VI vector<int>
#define VII vector<PII>
#define VID vector<pair<int,double>>
#define VDD vector<PDD>
using namespace std;
const int N=600100;
int a[N],b[N];
#if 0
struct Range{
int l,r,v;
} ;
int R[N],L[N];
//R[i]: i zui you bian de yi ge b shu zu bu shi 1 de wei zhi de zuo bian yi ge wei zhi
namespace t1{
struct qwq{
int l,r,mx,tag;
void init(int p){
l=r=p;
mx=L[p];
tag=-1;
}
void yhb(int v){
mx=(r-l+1)*v;
tag=v;
}
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
return {l.l,r.r,l.mx+r.mx,-1ll};
}
void build(int l,int r,int rt){
if(l==r)
return z[rt].init(l);
int mid=l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){
if(z[rt].tag!=-1){
z[rt<<1].yhb(z[rt].tag);
z[rt<<1|1].yhb(z[rt].tag);
z[rt].tag=-1;
}
}
void modify1(int l,int r,int rt,int ll,int rr,int v){
if(ll<=l&&r<=rr)
return z[rt].yhb(v);
int mid=l+r>>1;
pushyhb(rt);
if(ll<=mid)
modify1(l,mid,rt<<1,ll,rr,v);
if(mid<rr)
modify1(mid+1,r,rt<<1|1,ll,rr,v);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query1(int l,int r,int rt,int ll,int rr){
if(ll<=l&&r<=rr)
return z[rt].mx;
int mid=l+r>>1;
pushyhb(rt);
if(ll<=mid&&mid<rr)
return query1(l,mid,rt<<1,ll,rr)+query1(mid+1,r,rt<<1|1,ll,rr);
if(mid<rr)
return query1(mid+1,r,rt<<1|1,ll,rr);
return query1(l,mid,rt<<1,ll,rr);
}
}
namespace t2{
struct qwq{
int l,r,mx,tag;
void init(int p){
l=r=p;
mx=R[p];
tag=-1;
}
void yhb(int v){
mx=(r-l+1)*v;
tag=v;
}
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
return {l.l,r.r,l.mx+r.mx,-1ll};
}
void build(int l,int r,int rt){
if(l==r)
return z[rt].init(l);
int mid=l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){
if(z[rt].tag!=-1){
z[rt<<1].yhb(z[rt].tag);
z[rt<<1|1].yhb(z[rt].tag);
z[rt].tag=-1;
}
}
void modify1(int l,int r,int rt,int ll,int rr,int v){
if(ll<=l&&r<=rr)
return z[rt].yhb(v);
int mid=l+r>>1;
pushyhb(rt);
if(ll<=mid)
modify1(l,mid,rt<<1,ll,rr,v);
if(mid<rr)
modify1(mid+1,r,rt<<1|1,ll,rr,v);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query1(int l,int r,int rt,int ll,int rr){
if(ll<=l&&r<=rr)
return z[rt].mx;
int mid=l+r>>1;
pushyhb(rt);
if(ll<=mid&&mid<rr)
return query1(l,mid,rt<<1,ll,rr)+query1(mid+1,r,rt<<1|1,ll,rr);
if(mid<rr)
return query1(mid+1,r,rt<<1|1,ll,rr);
return query1(l,mid,rt<<1,ll,rr);
}
}
namespace t3{
struct qwq{
int l,r,mx,tag;
void init(int p){
l=r=p;
mx=a[p];
tag=-1;
}
void yhb(int v){
mx=(r-l+1)*v;
tag=v;
}
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
return {l.l,r.r,l.mx+r.mx,-1ll};
}
void build(int l,int r,int rt){
if(l==r)
return z[rt].init(l);
int mid=l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){
if(z[rt].tag!=-1){
z[rt<<1].yhb(z[rt].tag);
z[rt<<1|1].yhb(z[rt].tag);
z[rt].tag=-1;
}
}
void modify1(int l,int r,int rt,int ll,int rr,int v){
if(ll<=l&&r<=rr)
return z[rt].yhb(v);
int mid=l+r>>1;
pushyhb(rt);
if(ll<=mid)
modify1(l,mid,rt<<1,ll,rr,v);
if(mid<rr)
modify1(mid+1,r,rt<<1|1,ll,rr,v);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query1(int l,int r,int rt,int ll,int rr){
if(ll<=l&&r<=rr)
return z[rt].mx;
int mid=l+r>>1;
pushyhb(rt);
if(ll<=mid&&mid<rr)
return query1(l,mid,rt<<1,ll,rr)+query1(mid+1,r,rt<<1|1,ll,rr);
if(mid<rr)
return query1(mid+1,r,rt<<1|1,ll,rr);
return query1(l,mid,rt<<1,ll,rr);
}
}
//t1 维护 L
//t2 维护 R
//t3 维护 a
//b 不需要维护
#endif
struct qwq{
int l,r,cnt,ch,mx;
void init(int p){
l=r=p;
mx=a[p];
ch=b[p];
if(b[p]!=1)
cnt=1;
else
cnt=0;
}
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
return {l.l,r.r,l.cnt+r.cnt,0ll,l.mx+r.mx};
}
void build(int l,int r,int rt){
if(l==r)
return z[rt].init(l);
int mid=l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void modify1(int l,int r,int rt,int p,int v){
if(l==r){
z[rt].mx=v;
return;
}
int mid=l+r>>1;
if(p<=mid)
modify1(l,mid,rt<<1,p,v);
else
modify1(mid+1,r,rt<<1|1,p,v);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void modify2(int l,int r,int rt,int p,int x){
if(l==r){
z[rt].ch=x;
if(x!=1)z[rt].cnt=1;
else z[rt].cnt=0;
return;
}
int mid=l+r>>1;
if(p<=mid)
modify2(l,mid,rt<<1,p,x);
else
modify2(mid+1,r,rt<<1|1,p,x);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
PII query1(int l,int r,int rt,int ll,int rr){
if(l==r){
if(z[rt].cnt)return {l,rt};
else return {0,0};
}
int mid=l+r>>1;
if(ll<=l&&r<=rr){
if(z[rt<<1].cnt)
return query1(l,mid,rt<<1,ll,rr);
else
return query1(mid+1,r,rt<<1|1,ll,rr);
}else{
PII z={0,0};
if(ll<=mid)
z=query1(l,mid,rt<<1,ll,rr);
if(mid<rr&&!z.first) z=query1(mid+1,r,rt<<1|1,ll,rr);
return z;
}
}
int query2(int l,int r,int rt,int ll,int rr){
if(ll<=l&&r<=rr)
return z[rt].mx;
int mid=l+r>>1;
if(ll<=mid&&mid<rr)
return query2(l,mid,rt<<1,ll,rr)+query2(mid+1,r,rt<<1|1,ll,rr);
if(ll<=mid)
return query2(l,mid,rt<<1,ll,rr);
return query2(mid+1,r,rt<<1|1,ll,rr);
}
#ifndef THIS_IS_JIAOHUTI
signed main(){
// freopen("count_in","r",stdin);freopen("count.out","w",stdout);
ios_base::sync_with_stdio(0);cin.tie(0);
int n;cin>>n;
F(i,1,n)cin>>a[i];
F(i,1,n)cin>>b[i];
build(1,n,1);int q;cin>>q;
while(q--){
int o;cin>>o;
if(o==1){
int l,r;cin>>l>>r;
modify1(1,n,1,l,r);
}else if(o==2){
int l,r;cin>>l>>r;
modify2(1,n,1,l,r);
}else{
int l,r;cin>>l>>r;
int mx=0;
while(l<=r){
auto T=query1(1,n,1,l,r);
if(!T.first)break;
// cout<<"qwq "<<T.first<<' '<<T.second<<'\n';
if(T.first!=l)mx+=query2(1,n,1,l,T.first-1);
else;
mx=max(mx*z[T.second].ch,mx+z[T.second].mx);
l=T.first+1;
}
if(l<=r)
mx+=query2(1,n,1,l,r);
cout<<mx<<'\n';
}
}
}
#else
#define NO_MAIN
void no_main() {
puts("pwp");
}
#endif
本文来自博客园,作者:yhbqwq,转载请注明原文链接:https://www.cnblogs.com/yhbqwq/p/18378344,谢谢QwQ