AtCoder Beginner Contest 309

A.我直接打表把每个答案都弄出来了

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 110;
int n,m;
vector g[N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

void solve(){
    int a,b;
    g[1]={2};
    g[2]={1,3};
    g[3]={2};
    g[4]={5};
    g[5]={4,6};
    g[6]={4};
    g[7]={8};
    g[8]={7,9};
    g[9]={8};
    cin>>a>>b;
    for(auto&x:g[a]){
        if(x==b){
            cout<<"Yes\n";return ;
        }
    }
    cout<<"No\n";
                
}
int main()
{
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
}

B.直接也打表?

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include
using namespace std;
const int N = 110;
#define int long long
typedef pair PII;
int n,m;
vector g[N];
char a[N][N],b[N][N];
void solve(){
    cin>>n;
    for(int i=0;i>a[i];
    memcpy(b,a,sizeof(a));
    for(int i=0;i>t;
    while(t--) solve();
}

C.二分

因为药物全从1开始到某一天消失,所以吃的药只会越来越小,具有单调性,二分

然后统计大于等于这一天吃的药和k比即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e6+10;
#define int long long
typedef long long LL;
typedef pair PII;

int n,m,k;
PII a[N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

void solve(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i].first>>a[i].second;
    }
    sort(a+1,a+1+n,[&](const auto&p,const auto&q){
        return p.first=x)
            {
                now+=a[i].second;
            }    
        }
        if(now<=k) return true;
        else return false;
    };
    int l=1,r=2e9;
    while(l>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    cout<>t;
    while(t--) solve();
}

D.预处理出1点到自己那个连通块的点中最远的点,和n1+n2点在自己那个连通块最远的点连一起即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include
using namespace std;
const int N = 1e6+10;
#define int long long
typedef pair PII;
int n,m;
vector g[N];
void solve(){
    int n1,n2;
    cin>>n1>>n2>>n;
    for(int i=1;i<=n;i++)
    {
        int a,b;cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    vector dist1(n1+n2+10,0x3f3f3f3f);
    vector dist2(n1+n2+10,0x3f3f3f3f);
    auto bfs1=[&](int x)
    {
        dist1[x]=0;
        queue q;
        q.push(x);
        while(q.size()){
            auto u=q.front();
            q.pop();
            for(auto&i:g[u]){
                if(dist1[i]>dist1[u]+1){
                    dist1[i]=dist1[u]+1;
                    q.push(i);
                }
            }
        }
    };
    auto bfs2=[&](int x)
    {
        dist2[x]=0;
        queue q;
        q.push(x);
        while(q.size())
        {
            auto u=q.front();
            q.pop();
            for(auto&i:g[u])
            {
                if(dist2[i]>dist2[u]+1){
                    dist2[i]=dist2[u]+1;
                    q.push(i);
                }
            }
        }
    };
    bfs1(1);
    bfs2(n1+n2);
    int a=0,b=0;
    for(int i=0;i>t;
    while(t--) solve();
}

E.

大概就是把每个有保险的点入队

求最长路,因为从当前点到儿子节点要消耗1,边权是1

所以每个点求个最长路即可,最后统计哪些点能到就行

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e6+10;
using node=tuple;
int a[N];
int n,m;
int d[N];
int dist[N];
vector g[N];
void solve(){
    cin>>n>>m;
    for(int i=2;i<=n;i++){
        int p;cin>>p;
        g[p].push_back(i);
    }
    memset(d,-0x3f,sizeof(d));
    vector st(n+10,false);
    for(int i=1;i<=m;i++){
        int a,b;cin>>a>>b;
        d[a]=max(d[a],b);
    }
    priority_queue q;
    memset(dist,-0x3f,sizeof(dist));
    for(int i=1;i<=n;i++){
        if(d[i]!=-0x3f3f3f3f) q.emplace(d[i],i);
    }
    int res=0;

    while(q.size())
    {
        auto [t,u]=q.top();
        q.pop();
        if(t<=dist[u]||t<0) continue;
        st[u]=true;
        dist[u]=t;
        for(auto j:g[u])
        {
            q.emplace(max(t-1,d[j]),j);
        }
    }
    for(int i=1;i<=n;i++) res+=st[i];
    cout<>t;
    while(t--) solve();
}

F.

首先x,y,z排序,最小的跟最小比,这样肯定是可行的

先按照x排序,然后找比当前点的y小的值里面的最小值的z,

因为严格大于,所以枚举x的时候,用个map存在就能保证,要先等全部相同x枚举完才能一起把y放到线段树里面

因为y很大所以要先离散化

然后线段树求区间里面z最小值即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e6+10;


int n,m;
struct tree{
    int x,y,z;
}g[N];
map> mp;
vector num;
struct node{
    int l,r,mn;
}tr[N*4];
int find(int x){
    return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}
void pushup(int u){
    tr[u].mn=min(tr[u<<1].mn,tr[u<<1|1].mn);
}

void build(int u, int l, int r)
{
    if (l == r) tr[u] = {l, r,0x3f3f3f3f};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u,int x,int d){
    if(tr[u].l==tr[u].r&&tr[u].l==x){
        tr[u].mn=min(d,tr[u].mn);
        return ;
    }
    else{
        int mid=tr[u].l+tr[u].r>>1;
        if(x<=mid) modify(u<<1,x,d);
        else modify(u<<1|1,x,d);
        pushup(u);
    }
}

int query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r)
    {
        return tr[u].mn;  
    }
    else
    {
        int mid = tr[u].l + tr[u].r >> 1;
        int res = 0x3f3f3f3f;
        if (l <= mid ) res = query(u << 1, l, r);
        if (r > mid) res = min(res,query(u << 1 | 1, l, r));
        return res;
    }
}

void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        int a,b,c;cin>>a>>b>>c;
        vector d={a,b,c};
        sort(d.begin(),d.end());
        g[i]={d[0],d[1],d[2]};
    }
    for(int i=1;i<=n;i++) num.push_back(g[i].y),num.push_back(g[i].y-1);
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end());
    int m=num.size();
    build(1,0,m);
    for(int i=1;i<=n;i++){
        mp[g[i].x].push_back(i);
    }
    for(auto&[k,v]:mp)
    {
        bool f=false;
        for(int i=0;i>t;
    while(t--) solve();
}

你可能感兴趣的:(算法)