Educational Codeforces Round 10

A. Gabriel and Caterpillar

  模拟,注意爆int。

#include <bits/stdc++.h>

using namespace std;

int main(){
    ll h1,h2;
    ll a,b;
    cin>>h1>>h2>>a>>b;

    h1+=8*a;
    if(h1>=h2){
        cout<<0<<endl;
    }else{
        h1-=12*b;
        bool ok=0;
        for(int i=1;i<=200000;i++){
            h1+=12*a;
            if(h1>=h2){
                cout<<i<<endl;
                ok=1;
                break;
            }
            h1-=12*b;
        }
        if(!ok){
            cout<<-1<<endl;
        }
    }
    return 0;
}

B. z-sort

  排序以后,贪心从中间往两边取,一定有解的。

#include <bits/stdc++.h>

using namespace std;

int a[1111];

int main(){
    int n;
    cin>>n;

    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+n+1);

    int mid = (n+1)>>1;

    int l = mid+1;
    int r = mid;

    for(int i=1;i<=n;i++){
        if(i&1){
            l--;
            cout<<a[l]<<" ";
        }else{
            r++;
            cout<<a[r]<<" ";
        }
    }

    return 0;
}

C. Foe Pairs

  先把排列弄成升序,然后按左端点降序处理。逆序枚举区间起点,以此为起点的区间的终点不能“跃过”出现过的任何pair。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

int a[300010];
int mp[300010];

pair<int,int> ps[300010];

int main(){
    int n,m;
    cin>>n>>m;

    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        mp[a[i]] = i;
    }

    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        ps[i].first = mp[u];
        ps[i].second = mp[v];
        if(ps[i].first>ps[i].second){
            swap(ps[i].first,ps[i].second);
        }
    }   

    sort(ps+1,ps+m+1);

    ll ans = 0;
    int k=m;
    int MIN = n+1;
    for(int i=n;i>0;i--){
        while(ps[k].first>=i && k){
            MIN = min(MIN,ps[k].second);
            k--;
        }
        ll tmp = MIN-i;
        ans += tmp;
    }
    cout<<ans<<endl;

    return 0;
}

D. Nested Segments

  又一个区间问题。离散化,按区间右端点升序枚举,树状数组维护区间左端点的位置。每枚举到一个区间,根据当前左端点,在BIT中查询当前区间包含了多少区间,把区间左端点加入BIT。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 200010;

struct node{
    int l,r;
    int id;
    node(){
    }
    node(int l,int r):l(l),r(r){
    }

    bool operator<(const node& other)const{
        return r<other.r;
    }
}nds[maxn];

int b[maxn<<1];

int k;

int Find(int x){
    return lower_bound(b,b+k,x)-b+1;
}

int c[maxn<<1];

int ans[maxn];

inline int lowbit(int x){
    return x&(-x);
}

void update(int x){
    while(x<=400010){
        c[x]++;
        x+=lowbit(x);
    }
}

int query(int x){
    int ans = 0;
    while(x){
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}

int main(){
    int n;
    cin>>n;

    for(int i=0;i<n;i++){
        scanf("%d%d",&nds[i].l,&nds[i].r);
        nds[i].id = i;
        b[i<<1] = nds[i].l;
        b[(i<<1)+1] = nds[i].r;
    }

    k = n<<1;
    sort(b,b+k);
    k = unique(b,b+k) - b;

    for(int i=0;i<n;i++){
        nds[i].l = Find(nds[i].l);
        nds[i].r = Find(nds[i].r);
    }

    sort(nds,nds+n);

    int tot = 0;
    for(int i=0;i<n;i++){
        int q = query(nds[i].l);
        ans[nds[i].id] = tot-q;
        update(nds[i].l);
        tot++;
    }

    for(int i=0;i<n;i++){
        printf("%d\n",ans[i]);
    }

    return 0;
}

E. Pursuit For Artifacts

  因为走过的边不能再走,考虑双连通缩点,在同一个连通分量里的点肯定是可以绕完一圈的。缩点以后建立新图,相同连通分量内的边,如果上面有神器,就为这个分量做一个标记,可以认为只要路径能经过这个分量,就能拿到神器。不同连通分量之间的边,按原图建,注意不要删边。最后我们可以从起点的连通分量dfs到终点,如果路上经过有神器的连通分量或有神器的边,则输出YES。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;

bool vis[maxn];
int dfn[maxn];
int low[maxn];

struct Edge{
    int v;
    int w;
    Edge(int v,int w):v(v),w(w){
    }
    Edge(){
    }
}edges[maxn<<1],newedges[maxn<<1];

vector<int> oriG[maxn];

vector<int> G[maxn];

int dfs_clock = 0;

stack<int> sta;

int a,b;

int belong[maxn];
int hasArt[maxn];

bool instack[maxn];

void tarjan(int u,int p){  
    dfn[u]=low[u]=++dfs_clock;  
    sta.push(u);  
    instack[u]=1;  
    int sz=oriG[u].size();  
    for(int i=0;i<sz;i++){  
        int v= edges[oriG[u][i]].v;  
        if(v==p)continue;
        if(!dfn[v]){  
            tarjan(v,u);  
            low[u]=min(low[u],low[v]);  
        }else if(instack[v]){  
            low[u]=min(low[u],dfn[v]);  
        }  
    }

    if(low[u]==dfn[u]){  
        while(1){  
            int t=sta.top(); sta.pop(); instack[t]=0;  
            belong[t]=u;  
            if(t==u)break;
        }  
    }  
}  

int u[maxn];
int v[maxn];
int w[maxn];

bool ok = 0;

bool dfs(int u,int p){
    if(u==belong[b]){
        if(hasArt[u])ok=1;
        return 1;
    }
    int sz=G[u].size();  
    bool findB = 0;
    for(int i=0;i<sz;i++){
        int v = newedges[G[u][i]].v;
        if(v==p)continue;
        if(dfs(v,u)){
            findB = 1;
            if(newedges[G[u][i]].w){
                ok = 1;
            }
        }
    }
    if(findB && hasArt[u]){
        ok = 1;
    }
    return findB;
}

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&u[i],&v[i],&w[i]);
        edges[i<<1] = Edge(v[i],w[i]);
        oriG[u[i]].push_back(i<<1);
        edges[(i<<1)|1] = Edge(u[i],w[i]);
        oriG[v[i]].push_back((i<<1)|1);
    }

    cin>>a>>b;
    tarjan(a,-1);

    int k=0;
    for(int i=0;i<m;i++){
        int uu = belong[u[i]];
        int vv = belong[v[i]];
        if(uu==vv){
            if(w[i]){
                hasArt[uu] = 1;
            }
        }else{
            newedges[k] = Edge(vv,w[i]);
            G[uu].push_back(k++);
            newedges[k] = Edge(uu,w[i]);
            G[vv].push_back(k++);
        }
    }

    dfs(belong[a],-1);

    if(ok){
        cout<<"YES"<<endl;
    }else{
        cout<<"NO"<<endl;
    }

    return 0;
}

你可能感兴趣的:(codeforces)