AtCoder Beginner Contest 183 全题解

由于CF的比赛时间实在是有点晚,最近开启了AtCoder的比赛生涯.
Beginner的题目有点类似CF里的Div3.甚至要更简单一点.主要是题目给的样例基本上能把BUG都找出来.
A是语法题.
B是数学题.要注意的是尽量控制精度到题目给定误差的范围那里.不然会WA
太水就不给代码了

C是简单dfs.注意一下回到1的时候要把耗时也给加上就行了.
参考代码:

int t[10][10];
int K,vis[10],n,ans;
void dfs(int pre,int k,int val){
    
    
    if(k == n+1){
    
    
        if(val + t[pre][1] == K) ans++;
        return;
    }
    fir(i,2,n){
    
    
        if(vis[i]) continue;
        vis[i] = 1;
        dfs(i,k+1,val+t[pre][i]);
        vis[i] = 0;
    }
}
int main(){
    
    
    cin >> n >> K;
    fir(i,1,n){
    
    
        fir(j,1,n){
    
    
            cin >> t[i][j];
        }
    }
    vis[1] = 1;
    dfs(1,2,0);
    cout << ans;
     
    return 0;
}    

D 这题的难度在于读懂题目…其实就是给了一个区间加的操作,最后加完询问每个点是否都小于给定的W.一个树状数组即可水过去.注意一下区间不不包括T[i]的
参考代码:

int s[N],t[N],n,w;
LL c[N],p[N];
void add(int p,int v){
    
    
    for(;p<=2e5+1;p+=p&-p) c[p] += v;
}
LL ask(int p){
    
    
    LL res = 0;
    for(;p;p-=p&-p) res += c[p];
    return res;
}
int main(){
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> w;
    fir(i,1,n){
    
    
        cin >> s[i] >> t[i] >> p[i];
        s[i]++;
        t[i]++;
        add(t[i],-p[i]);
        add(s[i],p[i]);
    }
    fir(i,0,2e5){
    
    
        if(ask(i) > w){
    
    
            cout << "No\n";
            return 0;
        }
    }
    cout << "Yes\n";
    
    return 0;
}   

E 一个简单的DP问题.考虑到每个点都能从上方,左上方,左方的任意一个点转移过来,我们多维护一个sum数组维护一下前缀和即可.
注意一下虽然1e9相加不会爆int,但能开long long还是开long long吧.
参考代码:

const int p = 1e9+7;
string mz[2020];
LL dp[2020][2020],sum[2020][2020][3];
int main(){
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    cin >> n >> m;
    fir(i,1,n){
    
    
        cin >> mz[i];
        mz[i] = ' ' + mz[i];
    }
    dp[1][1] = 1;
    fir(i,1,n){
    
    
        fir(j,1,m){
    
    
            if(mz[i][j] == '#') continue;
            if(i != 1 || j != 1) dp[i][j] = (sum[i-1][j][0] + sum[i][j-1][1] + sum[i-1][j-1][2])%p;
            sum[i][j][0] = (dp[i][j]+sum[i-1][j][0])%p;
            sum[i][j][1] = (dp[i][j]+sum[i][j-1][1])%p;
            sum[i][j][2] = (dp[i][j]+sum[i-1][j-1][2])%p;
        }
    }
    cout << dp[n][m] << "\n";
    
    return 0;
}

F 启发式合并的裸题.每个人开一个动态的线段树即可.合并的时候把小的合并到大的里面,复杂度O(nlogn). 线段树合并博客

#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=(int)b;++i)
#define afir(i,a,b) for(int i=(int)a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#define mpr(a,b) make_pair(a,b)
#include <bits/stdc++.h>

using namespace std;
const int N = 2e5+10;

inline int read(){
    
    
    int x = 0,f=1;char ch = getchar();
    while(ch<'0'||ch>'9'){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){
    
    x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int fa[N],siz[N],root[N],n,m,a[N];
namespace seg{
    
    
    int tot,sum[N*20],ls[N*20],rs[N*20];
    void add(int &now,int l,int r,int p,int v){
    
    
        if(!now) now = ++ tot;
        sum[now]+=v;
        if(l == r) return;
        int mid = l + r >> 1;
        if(p <= mid) add(ls[now],l,mid,p,v);
        else add(rs[now],mid+1,r,p,v);
    }
    int ask(int now,int l,int r,int p){
    
    
        if(!now) return 0;
        if(l == r) return sum[now];
        int mid = l + r >> 1;
        if(p <= mid) return ask(ls[now],l,mid,p);
        return ask(rs[now],mid+1,r,p);
    }
    int merge(int x,int y){
    
    
        if(!x || !y) return x+y;
        sum[x] += sum[y];
        ls[x] = merge(ls[x],ls[y]);
        rs[x] = merge(rs[x],rs[y]);
        return x;
    }
}
int get(int x){
    
    
    int r = x;
    while(fa[r] != r) r = fa[r];
    int i=x,j=x;
    while(i != r){
    
    
        j = fa[i];
        fa[i] = r;
        i = j;
    }
    return r;
}
void merge(int x,int y){
    
    
    int fx = get(x),fy = get(y);
    if(siz[fx] > siz[fy]) return (void)merge(y,x);
    if(fx != fy){
    
    
        fa[fx] = fy;
        siz[fy] += siz[fx];
        root[y] = seg::merge(root[fy],root[fx]);
    }
}
int query(int x,int y){
    
    
    int fx = get(x);
    return seg::ask(root[fx],1,n,y);
}
int main(){
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    fir(i,1,n){
    
    
        cin >> a[i];
        siz[i] = 1;
        fa[i] = i;
        seg::add(root[i],1,n,a[i],1);
    }
    fir(i,1,m){
    
    
        int op,a,b;
        cin >> op >> a >> b;
        if(op == 1) merge(a,b);
        else cout << query(a,b) << "\n";
    }
    
    return 0;
}    

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/109956120