2024.10.26 2024 CCPC哈尔滨站

Solved:6/13

Penalty:635

Rank:72

Rank(ucup):170


打到后面困了(而且不会 L 心态爆炸)睡觉去了,不然还能多做个 E 题(

被 L 单防了啊。。


M. Weird Ceiling

定义 \(f(n,k)\) 如下:设 \(d\)\(n\) 小于等于 \(k\) 的最大约数,则 \(f(n,k) = \frac nd\)。求 \(\sum_{k=1}^n f(n,k)\)


将所有约数排序,然后枚举 \(d\) 即可。复杂度 \(O(\sqrt n)\)

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

void solve(){
    int n;
    cin>>n;
    vector<int> d;
    for(int i=1;i*i<=n;++i)if(!(n%i)){
        d.push_back(i);
        if(i!=n/i)d.push_back(n/i);
    }
    sort(d.begin(),d.end());
    ll ans=0;
    for(int i=0;i<d.size()-1;++i){
        ans+=1ll*(d[i+1]-d[i])*(n/d[i]);
    }
    ans+=1;
    cout<<ans<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

C. Giving Directions in Harbin

简单模拟,没啥好说的。

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

const int N=11;
string d[N];
int a[N];
void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;++i)cin>>d[i]>>a[i];
    vector<string> ans;
    vector<int> st;
    auto num=[](string x)->int {
        if(x=="S")return 0;
        if(x=="E")return 1;
        if(x=="N")return 2;
        if(x=="W")return 3;
    };
    auto turn=[&](string x,string y)->void {
        int t=num(x)-num(y);
        if(abs(t)>abs(t+4))t+=4;
        if(abs(t)>abs(t-4))t-=4;
        if(t>0){
            for(int i=0;i<t;++i)ans.push_back("R"),st.push_back(0);
        }
        else{
            for(int i=0;i<-t;++i)ans.push_back("L"),st.push_back(0);
        }
    };
    ans.push_back("Z"),st.push_back(a[1]);
    for(int i=2;i<=n;++i){
        turn(d[i-1],d[i]);
        ans.push_back("Z"),st.push_back(a[i]);
    }
    cout<<ans.size()<<' '<<d[1]<<'\n';
    for(int i=0;i<ans.size();++i){
        if(ans[i]=="Z")cout<<ans[i]<<' '<<st[i]<<'\n';
        else cout<<ans[i]<<'\n';
    }
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

G. Welcome to Join the Online Meeting!

\(n\) 个人,其中 \(m\) 对人互相认识。现在要让这 \(n\) 个人开一个会议,一开始只有一个人在会中,每个人可以把他认识的人拉进会议。有 \(k\) 个人在干活不能拉人。问能否把所有人都拉进会议,若能要给出方案。


选一个不在干活的人开始,然后bfs即可。

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

const int N=2e5+5;
int n,m,k,x,y;
bool b[N],vis[N];
vector<int> e[N];
void adde(int x,int y){
    e[x].push_back(y);
}

int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=k;++i)cin>>x,b[x]=1;
    for(int i=1;i<=m;++i)cin>>x>>y,adde(x,y),adde(y,x);
    queue<int> q;
    for(int i=1;i<=n;++i)if(!b[i]){q.push(i),vis[i]=1;break;}
    vector<vector<int>> ans;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        if(b[u])continue;
        vector<int> c;
        c.push_back(u);
        for(int v:e[u])if(!vis[v])c.push_back(v),q.push(v),vis[v]=1;
        if(c.size()>1)ans.push_back(c);
    }
    int cnt=0;
    for(int i=1;i<=n;++i)if(!vis[i])++cnt;
    if(cnt){cout<<"No\n";return 0;}
    cout<<"Yes\n";
    cout<<ans.size()<<'\n';
    for(auto c:ans){
        cout<<c[0]<<' '<<c.size()-1<<' ';
        for(int i=1;i<c.size();++i)cout<<c[i]<<' ';
        cout<<'\n';
    }
}

K. Farm Management

\(n\) 种作物,第 \(i\) 种作物可以种 \(l_i\)\(r_i\) 个单位,单位收益为 \(w_i\)
你一共可以种 \(m\) 个单位的作物,且你可以选择至多一种作物解除限制。
求最大收益。


贪心。
先把所有作物按收益从大到小排序,枚举解除限制的作物(假设是第 \(i\) 种)。
两种情况,一种是完全不种第 \(i\) 种作物,一种是所有余量都种第 \(i\) 种作物。
第二种情况显然只能 \(i=1\),第一种情况需要枚举 \(i\) 并预处理 \((r_i-l_i)\)\((r_i-l_i)w_i\) 的前缀和。

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

const int N=1e5+5;
int n;
ll m;
struct node{
    int l,r,w;
    bool operator<(const node& p)const{
        return w<p.w;
    }
}a[N];
ll s[N],sum[N];

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;++i)cin>>a[i].w>>a[i].l>>a[i].r;
    sort(a+1,a+n+1);
    ll now=0,sl=0;
    for(int i=1;i<=n;++i)now+=1ll*a[i].w*a[i].l,sl+=a[i].l;
    ll ans=now+1ll*a[n].w*(m-sl);
    for(int i=1;i<=n;++i){
        s[i]=s[i-1]+a[n-i+1].r-a[n-i+1].l;
        sum[i]=sum[i-1]+1ll*a[n-i+1].w*(a[n-i+1].r-a[n-i+1].l);
    }
    for(int i=1;i<=n;++i){
        int pos=upper_bound(s+1,s+n+1,m-sl+a[i].l)-s;
        ans=max(ans,now-1ll*a[i].w*a[i].l+sum[pos-1]+1ll*a[n-pos+1].w*(m-sl+a[i].l-s[pos-1]));
    }
    cout<<ans<<'\n';
}

J. New Energy Vehicle

\(n\) 种汽油,\(m\) 个加油站,每个加油站只能加一种油,每种油都是一单位能走一公里,求最远能走多少公里。\(n,m\leq 10^5\)


贪心,优先用下次出现最早的那种油。

set<pair<int,int>> 维护(下次出现位置,编号)即可。

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

const int N=1e5+5;
int n,m,a[N],c[N],x[N],t[N],fir[N],lst[N],nxt[N];
ll solve(){
    cin>>n>>m;
    for(int i=1;i<=n;++i)cin>>a[i],c[i]=a[i];
    for(int i=1;i<=m;++i)cin>>x[i]>>t[i];
    for(int i=1;i<=n;++i)fir[i]=m+1,lst[i]=0;
    for(int i=1;i<=m;++i){
        if(fir[t[i]]>m)fir[t[i]]=i;
        if(lst[t[i]])nxt[lst[t[i]]]=i;
        lst[t[i]]=i;
    }
    for(int i=1;i<=n;++i)if(lst[i])nxt[lst[i]]=m+1;
    set<pii> s;
    for(int i=1;i<=n;++i)s.insert(pii(fir[i],i));
    ll sum=0;
    for(int i=1;i<=m;++i){
        int r=x[i]-x[i-1];
        while(!s.empty()&&c[s.begin()->second]<=r){
            int k=s.begin()->second;
            sum+=c[k],r-=c[k],c[k]=0;
            s.erase(s.begin());
        }
        if(s.empty()&&r>0)return sum;
        c[s.begin()->second]-=r,sum+=r;
        c[t[i]]=a[t[i]];
        if(s.find(pii(i,t[i]))!=s.end())s.erase(pii(i,t[i]));
        s.insert(pii(nxt[i],t[i]));
    }
    for(int i=1;i<=n;++i)sum+=c[i];
    return sum;
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)cout<<solve()<<'\n';
}

A. Build a Computer

构造一个有限状态自动机,使其能且只能识别\([L,R]\)范围内的所有二进制串(无前导零)。

\(1\leq L\leq R\leq 10^6\),不能超过 100 个节点。


直接造 trie 树节点数多达 2e6,肯定不行。

注意到很多子树都是满二叉树,我们可以用一条01重边的链把这些满二叉树全都缩掉,即如果这个节点是满二叉树就直接连到链上。这样可以证明总点数不超过 \(5\log n\),正好在 100 的范围内。

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

const int N=105;
int L,R,c[N][2],tot,rt,m;
void dfs(int &x,int L,int R,int l,int r,int k){
    if(l==L&&r==R){
        m=max(m,k),x=-k;
        return;
    }
    x=++tot;
    int mid=(l+r)>>1;
    if(L<=mid)dfs(c[x][0],L,min(R,mid),l,mid,k-1);
    if(R>mid)dfs(c[x][1],max(L,mid+1),R,mid+1,r,k-1);
}

vector<pii> e[N];
void adde(int x,int y,int z){
    e[x].push_back(pii(y,z));
}
bool del[N];
int id[N];
int ID(int x){return x>0?id[x]:-x;}
int main(){
    cin>>L>>R;
    dfs(rt,L,R,0,(1<<__lg(R)+1)-1,__lg(R)+2);
    int cnt=m;
    for(int i=m;i>1;--i)adde(i,i-1,0),adde(i,i-1,1);
    int r=rt;
    while(c[r][0])del[c[r][0]]=1,r=c[r][0];
    for(int i=1;i<=tot;++i)if(!del[i])id[i]=++cnt;
    r=rt;
    while(r)adde(ID(rt),ID(c[r][1]),1),r=c[r][0];
    for(int i=2;i<=tot;++i)if(!del[i]){
        if(c[i][0]&&!del[c[i][0]])adde(id[i],ID(c[i][0]),0);
        if(c[i][1])adde(id[i],ID(c[i][1]),1);
    }
    cout<<cnt<<'\n';
    for(int i=1;i<=cnt;++i){
        cout<<e[i].size()<<' ';
        for(auto [x,y]:e[i])cout<<x<<' '<<y<<' ';
        cout<<'\n';
    }
}
posted @ 2024-10-29 21:38  EssnSlaryt  阅读(233)  评论(0编辑  收藏  举报