Solved:7/13
Penalty:793
Rank:40
Rank(ucup):152
L. Recover Statistics
輸出 50 個 P50、45 個 P95,4 個 P99 和 1 個 P99+1 即可。
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int a,b,c;
cin>>a>>b>>c;
cout<<100<<'\n';
for(int i=1;i<=50;++i)cout<<a<<' ';
for(int i=1;i<=45;++i)cout<<b<<' ';
for(int i=1;i<=4;++i)cout<<c<<' ';
cout<<c+1<<'\n';
}
A. Arrow a Row
題意:用形如 >—>>> (中間可以有任意多個 -)來構造給定字串,如果可以輸出方案。\(n\leq 2\times 10^5\)。
簡單構造,但是卡了很久。
結論是 a[1],a[n-2],a[n-1],a[n]必須是>,且至少要有一個-。
構造就是先把最後一段連續的>都造出來,再造前面的>。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
void solve(){
string a;
cin>>a;
int n=a.size();
if(a[0]=='-'||a[n-1]=='-'||a[n-2]=='-'||a[n-3]=='-'){
cout<<"No\n";
return;
}
int pos=-1;
for(int i=n-4;i>=0;--i)if(a[i]=='-'){pos=i;break;}
if(!~pos){
cout<<"No\n";
return;
}
vector<pii> ans;
for(int i=n-1;i>=pos+3;--i)ans.emplace_back(0,i);
for(int i=1;i<pos;++i)if(a[i]=='>')ans.emplace_back(i,pos+3);
cout<<"Yes "<<ans.size()<<'\n';
for(int i=0;i<ans.size();++i)cout<<ans[i].first+1<<' '<<ans[i].second-ans[i].first+1<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
G.Expanding Array
題意:給一個序列,每次可以在兩個數中間插入它們的按位與、按位或、按位異或。問最多能構造出多少個不同的數。\(n\leq 2\times 10^5\)。
能構造出的數只有 \(0,a_i,a_i\land a_{i+1},a_i\lor a_{i+1},a_i\oplus a_{i+1},a_i\backslash a_{i+1},a_{i+1}\backslash a_i\)。全都扔進 set 然後輸出 size 即可。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int n;
cin>>n;
vector<int> a(n);
for(int& x:a)cin>>x;
set<int> s;
s.insert(0);
for(int i=0;i<a.size()-1;++i){
s.insert(a[i]);
s.insert(a[i+1]);
s.insert(a[i]&a[i+1]);
s.insert(a[i]|a[i+1]);
s.insert(a[i]^a[i+1]);
s.insert(a[i]&(a[i]^a[i+1]));
s.insert(a[i+1]&(a[i]^a[i+1]));
}
cout<<s.size()<<'\n';
}
I.Good Partitions
題意:維護一個序列,支援單點修改,查詢存在多少個 \(k\) 滿足將序列分成每 \(k\) 個一段每段都是單調不減的。\(n\leq 2\times 10^5\)。
設所有滿足 \(a_i>a_{i+1}\) 的 \(i\) 的集合為 \(S\),則答案就是 \(\gcd(S)\)。
因此只需支援插入、刪除一個數,維護全體的 \(\gcd\)。
一開始寫了個逆天的 vector 套 set,要列舉約數複雜度達到了 \(O((n+q)d(n)\log n)\),然後 TLE on 13。
然後改成了線段樹維護 gcd,不存在的位置就填 0,複雜度 \(O(n\log^2 n)\)。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+5;
int d[N];
void init(int n){
for(int i=1;i<=n;++i)
for(int j=i;j<=n;j+=i)++d[j];
}
#define lc (x<<1)
#define rc (x<<1|1)
#define mid ((l+r)>>1)
int n,q,x,y,a[N],s[N*4];
void bld(int x,int l,int r){
if(l==r){s[x]=a[l]>a[l+1]?l:0;return;}
bld(lc,l,mid),bld(rc,mid+1,r);
s[x]=__gcd(s[lc],s[rc]);
}
void upd(int x,int l,int r,int p,int v){
if(l==r){s[x]=v;return;}
if(p<=mid)upd(lc,l,mid,p,v);
else upd(rc,mid+1,r,p,v);
s[x]=__gcd(s[lc],s[rc]);
}
void solve(){
cin>>n>>q,d[0]=n;
for(int i=1;i<=n;++i)cin>>a[i];
if(n==1){
cout<<1<<'\n';
while(q--)cin>>x>>y,cout<<1<<'\n';
return;
}
bld(1,1,n-1);
cout<<d[s[1]]<<'\n';
while(q--){
cin>>x>>y;
if(x>1&&a[x-1]>a[x]&&a[x-1]<=y)upd(1,1,n-1,x-1,0);
if(x>1&&a[x-1]<=a[x]&&a[x-1]>y)upd(1,1,n-1,x-1,x-1);
if(x<n&&a[x]>a[x+1]&&y<=a[x+1])upd(1,1,n-1,x,0);
if(x<n&&a[x]<=a[x+1]&&y>a[x+1])upd(1,1,n-1,x,x);
a[x]=y;
cout<<d[s[1]]<<'\n';
}
}
int main(){
init(2e5);
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
J. Grand Prix of Ballance
簡單模擬,map 亂殺。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
const int N=1e5+5;
int n,m,q,op,id,x;
pii a[N];
int r[N];
set<pii> e;
void solve(){
cin>>n>>m>>q;
for(int i=1;i<=m;++i)a[i]={0,i};
memset(r,0,sizeof(int)*(n+1));
e.clear();
int cur=0;
while(q--){
cin>>op;
if(op==1){
cin>>x;
cur=x;
}
else if(op==2){
cin>>id>>x;
if(x!=cur||e.find(pii(id,x))!=e.end())continue;
a[id].first-=m-r[x];
e.insert({id,x}),++r[x];
}
else{
cin>>id>>x;
if(x!=cur||e.find(pii(id,x))!=e.end())continue;
e.insert({id,x});
}
}
sort(a+1,a+m+1);
for(int i=1;i<=m;++i)cout<<a[i].second<<' '<<-a[i].first<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;
cin>>T;
while(T--)solve();
}
B. Athlete Welcome Ceremony
題意:一個全是abc的字串,其中某些位置未定,要求相鄰位置不同,多次詢問,每次詢問限制 a 的數量不超過 x,b 的數量不超過 y,c 的數量不超過 z,求方案數。 \(1\leq n\leq 300,1\leq q\leq 10^5\)。
先 dp 求出 恰好使用 i 個 a、j 個 b、k 個 c 的方案數,然後三維字首和。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
const int N=305,mod=1e9+7;
int n,q,c[3];
string a;
ll f[N][N][N][3],s[N][N][N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>q>>a,a=" "+a;
for(int i=1;i<=n;++i)if(a[i]!='?')++c[a[i]-'a'];
f[1][0][0][0]=f[0][1][0][1]=f[0][0][1][2]=1;
for(int i=0;i<=n;++i)
for(int j=0;i+j<=n;++j)
for(int k=0;i+j+k<=n;++k)if(i+j+k>0){
if(a[i+j+k]=='a')f[i][j][k][1]=f[i][j][k][2]=0;
if(a[i+j+k]=='b')f[i][j][k][0]=f[i][j][k][2]=0;
if(a[i+j+k]=='c')f[i][j][k][0]=f[i][j][k][1]=0;
if(i+j+k<n){
(f[i+1][j][k][0]+=f[i][j][k][1]+f[i][j][k][2])%=mod;
(f[i][j+1][k][1]+=f[i][j][k][0]+f[i][j][k][2])%=mod;
(f[i][j][k+1][2]+=f[i][j][k][0]+f[i][j][k][1])%=mod;
}
}
for(int i=0;i<=n;++i)
for(int j=0;j<=n;++j)
for(int k=0;k<=n;++k){
if(i+j+k==n)s[i][j][k]=f[i][j][k][0]+f[i][j][k][1]+f[i][j][k][2];
if(i>0)s[i][j][k]+=s[i-1][j][k];
if(j>0)s[i][j][k]+=s[i][j-1][k];
if(k>0)s[i][j][k]+=s[i][j][k-1];
if(i>0&&j>0)s[i][j][k]-=s[i-1][j-1][k];
if(i>0&&k>0)s[i][j][k]-=s[i-1][j][k-1];
if(j>0&&k>0)s[i][j][k]-=s[i][j-1][k-1];
if(i>0&&j>0&&k>0)s[i][j][k]+=s[i-1][j-1][k-1];
s[i][j][k]=(s[i][j][k]%mod+mod)%mod;
}
while(q--){
int x,y,z;
cin>>x>>y>>z;
x=min(x+c[0],n),y=min(y+c[1],n),z=min(z+c[2],n);
cout<<s[x][y][z]<<'\n';
}
}
K. Magical Set
題意:給一個集合,每次可選一個數除掉它的一個非 1 約數,且需保證集合中任何時刻沒有相同的數。求最多能操作的次數。
最優方案下每次一定除的一定是質數。因此求出每個數及其所有約數的質因子數量 \(p_i\),然後對每個數向它的約數連一條 \(p_i-p_j\) 的邊,二分圖最大權匹配即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
const int V=6e5+5,E=3e7+5,inf=0x3f3f3f3f;
int s,t,v=0,e=1,fir[V],to[E],nxt[E],w[E],c[E];
inline void adde(int x,int y,int z,int t){
to[++e]=y,nxt[e]=fir[x],fir[x]=e,w[e]=z,c[e]=t;
to[++e]=x,nxt[e]=fir[y],fir[y]=e,w[e]=0,c[e]=-t;
}
int dis[V],q[E];
bool vis[V];
bool spfa(){
memset(dis,63,sizeof(dis));
memset(vis,0,sizeof(vis));
int l=1,r=0;
q[++r]=t,dis[t]=0;
while(l<=r){
int u=q[l++];vis[u]=0;
for(int i=fir[u],v=to[i];i;v=to[i=nxt[i]]){
if(!w[i^1]||dis[v]<=dis[u]+c[i^1])continue;
dis[v]=dis[u]+c[i^1];
if(!vis[v])vis[v]=1,q[++r]=v;
}
}
return dis[s]<inf;
}
int cur[V];
int dfs(int u,int flow){
if(u==t||!flow)return flow;
vis[u]=1;
int nowf=flow;
for(int& i=cur[u];i;i=nxt[i]){
int v=to[i];
if(dis[v]+c[i]!=dis[u]||vis[v])continue;
int f=dfs(v,min(w[i],nowf));
w[i]-=f,w[i^1]+=f;
if(!(nowf-=f))return flow;
}
return flow-nowf;
}
int MCMF(){
int flow=0,res=0;
while(spfa()){
memcpy(cur,fir,sizeof(cur));
memset(vis,0,sizeof(vis));
int f=dfs(s,inf);
flow+=f,res+=dis[s]*f;
}return res;
}
const int N=305;
map<int,int> id;
int n,a[N],p[V];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
s=++v,t=++v;
for(int i=1;i<=n;++i){
cin>>a[i];
if(!id.count(a[i]))id[a[i]]=++v;
adde(s,id[a[i]],1,0);
for(int j=1;j*j<=a[i];++j)if(!(a[i]%j)){
if(!id.count(j))id[j]=++v;
if(!id.count(a[i]/j))id[a[i]/j]=++v;
}
}
for(auto &[x,u]:id){
int tt=x;
for(int i=2;i*i<=tt;++i)if(!(tt%i)){
while(!(tt%i))tt/=i,++p[u];
}
if(tt>1)++p[u];
adde(u,t,1,0);
}
for(int i=1;i<=n;++i)
for(auto &[x,u]:id)
if(!(a[i]%x))adde(id[a[i]],u,1,-(p[id[a[i]]]-p[u]));
cout<<-MCMF()<<'\n';
}