2024.10.30 2022廣西省賽

EssentialSingularity發表於2024-10-30

Solved:11/12

Penalty:1059

Rank:1/146(N+2)

Dirt:48%

Problem A B C D E F G H I J K L 題數 罰時
Time 11 2 214 127 107 61 28 39 84 159 16 11 1059
dirt 3 1 1 3 2

A,B,G,H,L:簽到


F

直接扔一個帶修莫隊板子上去就過了。雖然1000的值域應該有點說法。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MN=2e5+5;
struct QUE{int l,r,t,id,typ,ans;}q[MN];
struct UPD{int fr,to,x;}u[MN];
int N,M,T,a[MN],pos[MN],totq,totu;
int ans;
inline bool cmp(const QUE&o,const QUE&oo)
{return (pos[o.l]^pos[oo.l])?(pos[o.l]<pos[oo.l]):((pos[o.r]^pos[oo.r])?(pos[o.r]<pos[oo.r]):(o.t<oo.t));}
int num[1000005];
inline bool cmp2(const QUE&o,const QUE&oo){return o.id<oo.id;}

int main()
{
    cin>>N>>M;
    T=1357;
    for(int i=1;i<=N;++i) cin>>a[i],pos[i]=(i-1)/T+1;
    for(int i=1;i<=M;++i)
    {
        int op;
        cin>>op;
        if(op==1||op==2)
        {
            ++totq;
            cin>>q[totq].l>>q[totq].r;
            q[totq].id=totq;
            q[totq].typ=op;
            q[totq].t=totu;
        }
        else
        {
            ++totu;
            cin>>u[totu].x;
            cin>>u[totu].to;
            u[totu].fr=a[u[totu].x];
            a[u[totu].x]=u[totu].to;
        }
    }
    for(int i=totu;i;--i) a[u[i].x]=u[i].fr;
    std::sort(q+1,q+totq+1,cmp);
    register int i=1,j=0,l=1,r=0,ans=0;
    for(i=1;i<=totq;++i)
    {
        for(;l>q[i].l;--l) ans+=((num[a[l-1]]^=1)?1:-1);
        for(;l<q[i].l;++l) ans+=((num[a[l]]^=1)?1:-1);
        for(;r<q[i].r;++r) ans+=((num[a[r+1]]^=1)?1:-1);
        for(;r>q[i].r;--r) ans+=((num[a[r]]^=1)?1:-1);
        for(;j<q[i].t;++j)
        {
            a[u[j+1].x]=u[j+1].to;
            if(u[j+1].x<=q[i].r&&u[j+1].x>=q[i].l)
                ans+=((num[u[j+1].fr]^=1)?1:-1),ans+=((num[u[j+1].to]^=1)?1:-1);
        }
        for(;j>q[i].t;--j)
        {
            a[u[j].x]=u[j].fr;
            if(u[j].x<=q[i].r&&u[j].x>=q[i].l)
                ans+=((num[u[j].fr]^=1)?1:-1),ans+=((num[u[j].to]^=1)?1:-1);
        }
        q[i].ans=q[i].typ==1?(ans==0||ans==1000):ans;
    }
    std::sort(q+1,q+totq+1,cmp2);
    for(i=1;i<=totq;++i) printf("%d\n",q[i].ans);
}

I

結論:當且僅當\(a\)\(b\)的原根(特判\(b=2\))。

證明:考慮模b剩餘系下的操作,則加b操作相當於沒有,因此想取到所有的數必須要a的冪次遍歷1到b-1,必要性得證。充分性考慮透過一系列操作得到若干\(k_rb+r(r=1,2,\dots,b-1)\),那隻需要把這些數加充分多個b就能讓它們變成連續段,後面的數就只要不斷加b就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e6;
bool vis[N];
int main(){
    int a,b;
    cin>>a>>b;
    a%=b;
    if(a==1){
        if(b<=2)cout<<"YES\n";
        else cout<<"NO\n";
        return 0;
    }
    vis[0]=vis[1]=1;
    ll r=a;
    while(!vis[r]){
        vis[r]=1;
        r=r*a%b;
    }
    bool fl=1;
    for(int i=0;i<b;++i)
        if(!vis[i]){fl=0;break;}
    cout<<(fl?"YES":"NO")<<'\n';
}

E

模擬題,寫得清楚點就行。

set會T(垃圾pta)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e6+5;

int m,c[2],o;
int mx[2][2],mn[2][2];
ll w[2][2];

string op[4]={"EF","EFX","EF1","E"};

int check(int x,int y){
    if(w[x][x]>=w[x][y])return 0;
    if(w[x][x]>=w[x][y]-mn[x][y])return 1;
    if(w[x][x]>=w[x][y]-mx[x][y])return 2;
    return 3;
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>m;
    mn[0][0]=mn[0][1]=mn[1][0]=mn[1][1]=2e9;
    for(int i=1;i<=m;++i){
        cin>>c[0]>>c[1]>>o;
        mx[0][o]=max(mx[0][o],c[0]);
        mn[0][o]=min(mn[0][o],c[0]);
        mx[1][o]=max(mx[1][o],c[1]);
        mn[1][o]=min(mn[1][o],c[1]);
        w[0][o]+=c[0];
        w[1][o]+=c[1];
        cout<<op[max(check(0,1),check(1,0))]<<'\n';
    }
}

D

分層圖最短路。建\(\log w\)層,第k層表示加速k次的圖。加速的點連向下一層的同一個點,壞路直接連回第0層。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,int> pll;

const int N=2e4*21+5;
int id(int x,int i){return (x-1)*21+i;}
vector<pii> e[N];
void adde(int x,int y,int z){
    e[x].push_back(pii(y,z));
}
int n,m,S,T,x,y,z,p;
string ch;
ll dis[N];
bool vis[N];

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>n>>m>>S>>T;
    for(int i=1;i<=m;++i){
        string ch;
        cin>>x>>y>>z>>ch;
        if(ch=="G"){
            for(int j=0;j<=20;++j)adde(id(x,j),id(y,j),(z+(1<<j)-1)>>j);
        }
        else{
            for(int j=0;j<=20;++j)adde(id(x,j),id(y,0),(z+(1<<j)-1)>>j);
        }
    }
    cin>>p;
    for(int i=1;i<=p;++i){
        cin>>x>>z;
        for(int j=0;j<20;++j)adde(id(x,j),id(x,j+1),z);
    }
    priority_queue<pll,vector<pll>,greater<pll>> pq;
    memset(dis,63,sizeof(dis));
    dis[id(S,0)]=0;
    pq.push(pll(0,id(S,0)));
    while(!pq.empty()){
        int u=pq.top().second;
        pq.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(auto [v,w]:e[u]){
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                pq.push(pll(dis[v],v));
            }
        }
    }
    ll ans=1e18;
    for(int i=0;i<=20;++i)ans=min(ans,dis[id(T,i)]);
    if(ans>1e16)cout<<"-1\n";
    else cout<<ans<<'\n';
}

J

dp+容斥。暴力列舉約數更新即可。

\[f_i=\sum_{d\neq 1, d|a_i}-\mu(d)g_{d,i}, g_{d,i} = g_{d,i-1}+f_i[d|i] \]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+5,mod=1e9+7;
bool np[N];
int pri[N],cnt,mu[N];
void sieve(int n){
    for(int i=2;i<=n;++i){
        if(!np[i])pri[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt&&i*pri[j]<=n;++j){
            np[i*pri[j]]=1;
            if(!(i%pri[j]))break;
            mu[i*pri[j]]=-mu[i];
        }
    }
}

int n,x;
ll f[N],g[N];

int main(){
    sieve(1e5);
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>n;
    f[1]=1;
    for(int i=1;i<=n;++i){
        cin>>x;
        for(int j=1;j*j<=x;++j)if(!(x%j)){
            f[i]=(f[i]-mu[j]*g[j])%mod;
            if(j*j<x)f[i]=(f[i]-mu[x/j]*g[x/j])%mod;
        }
        for(int j=1;j*j<=x;++j)if(!(x%j)){
            g[j]=(g[j]+f[i])%mod;
            if(j*j<x)g[x/j]=(g[x/j]+f[i])%mod;
        }
    }
    cout<<(f[n]%mod+mod)%mod<<'\n';
}

C

你們出字串都喜歡板子套板子嗎.jpg

對所有串的正串和反串分別建一棵trie,把結束節點的二元組記下來。

對每個詢問,相當於查詢x[i]在a在T1中的節點子樹、y[i]在b在T2中的節點子樹的二元組數量。

DFS序轉一下,就變成靜態矩陣求和了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+5,MN=1e6+5;
string rev(string s){
    int len=s.length();
    for(int i=0;i<len-i-1;++i)swap(s[i],s[len-i-1]);
    return s;
}
int n,m;
struct trie{
    int tot,c[MN][26],val[MN],dfn[MN],nfd[MN],id,sz[MN];
    trie(){tot=1,id=0;}
    int insert(string s){
        int u=1;
        for(char ch:s){
            int o=ch-'a';
            if(!c[u][o])c[u][o]=++tot;
            u=c[u][o];
        }
        return u;
    }
    void dfs(int u){
        dfn[u]=++id,nfd[id]=u,sz[u]=1;
        for(int i=0;i<26;++i)if(c[u][i])dfs(c[u][i]),sz[u]+=sz[c[u][i]];
    }
    int find(string s){
        int u=1;
        for(int ch:s){
            int o=ch-'a';
            if(!c[u][o])return 0;
            u=c[u][o];
        }
        return u;
    }
}T[2];

int pos[MN],tim[MN];

int cnt=0;
struct QUE{
    int id,x,y,typ;
    bool operator<(const QUE& q)const{
        return x<q.x;
    }
}q[N*2];
int ans[N];

int c[MN];
void upd(int x,int y){
    for(;x<=T[1].tot;x+=x&-x)c[x]+=y;
}
int qry(int x){
    int r=0;
    for(;x;x-=x&-x)r+=c[x];
    return r;
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        string s;
        cin>>s;
        int u=T[0].insert(s);
        int v=T[1].insert(rev(s));
        pos[u]=v,++tim[u];
    }
    T[0].dfs(1);
    T[1].dfs(1);
    for(int i=1;i<=m;++i){
        string s,t;
        cin>>s>>t;
        int u=T[0].find(s),v=T[1].find(rev(t));
        if(u&&v){
            q[++cnt]=(QUE){i,T[0].dfn[u]-1,v,-1};
            q[++cnt]=(QUE){i,T[0].dfn[u]+T[0].sz[u]-1,v,1};
        }
    }
    sort(q+1,q+cnt+1);
    for(int i=1,j=1;i<=T[0].tot;++i){
        if(pos[T[0].nfd[i]])upd(T[1].dfn[pos[T[0].nfd[i]]],tim[T[0].nfd[i]]);
        while(q[j].x==i){
            ans[q[j].id]+=q[j].typ*(qry(T[1].dfn[q[j].y]+T[1].sz[q[j].y]-1)-qry(T[1].dfn[q[j].y]-1));
            ++j;
        }
    }
    for(int i=1;i<=m;++i)cout<<ans[i]<<'\n';
}

相關文章