AtCoder Beginner Contest 378

AtCoder Beginner Contest 378 总结

A

直接模拟,存 \(1\)\(4\) 出现个数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1;
map<int,int> H;
void solve()
{
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    H[a]++,H[b]++,H[c]++,H[d]++;
    int ans=0;
    for(int i=1;i<=4;i++) ans+=H[i]/2;
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


B

要确定 \(d\) 处于哪一段区间内,分类讨论一下就能出来。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=105;
int n,m;
ll q[N],r[N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>q[i]>>r[i];
    cin>>m;
    while(m--)
    {
        ll t,d;
        cin>>t>>d;
        if(d<=r[t]) cout<<r[t]<<'\n';
        else 
        {
            if((d-r[t])/q[t]*q[t]==d-r[t]) cout<<d<<'\n';
            else cout<<(d-r[t])/q[t]*q[t]+r[t]+q[t]<<'\n';
        }
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


C

每次更新该值出现的位置,用 map 记录,如果出现了就输出位置,否则输出 \(-1\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int a[N];
map<ll,int> H;
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(H.count(a[i])) cout<<H[a[i]]<<' ';
        else cout<<-1<<' ';
        H[a[i]]=i;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


D

观察数据的范围都很小,直接用 dfs 模拟。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=15;
int n,m,k;
char g[N][N];
bool v[N][N];
int fx[]={0,0,1,-1};
int fy[]={1,-1,0,0};
int dfs(int x,int y,int cnt)
{
    if(cnt==k) return 1;
    int ret=0;
    v[x][y]=1;
    for(int i=0;i<4;i++) 
    {
        int nx=x+fx[i],ny=y+fy[i];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!v[nx][ny]&&g[nx][ny]=='.') 
            ret+=dfs(nx,ny,cnt+1);
    }
    v[x][y]=0;
    return ret;
}
void solve()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) 
            cin>>g[i][j];
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(g[i][j]=='.') 
                ans+=dfs(i,j,0);
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


E

要推一下式子:

\(S_i = (A_1+A_2+\dots+A_i) \mathbin{\mathrm{mod}} M\),就有:

\[ \sum_{1 \leq l \leq r \leq N} \left( \left(\sum_{l \leq i \leq r} A_i\right) \mathbin{\mathrm{mod}} M \right) = \sum_{1 \leq l \leq r \leq N} (S_r - S_{l-1}) \mathbin{\mathrm{mod}} M \]

然后因为 \(0 \leq S_{l-1},S_r < M\),所以

\[ (S_r - S_{l-1}) \mathbin{\mathrm{mod}} M = S_r - S_{l-1} + \begin{cases} 0 & (S_{l-1} \leq S_r) \\ M & (S_{l-1} > S_r)\end{cases} \]

这样就去掉了取模。

\(X_r\) 为在 \(S_0\)\(S_{r-1}\) 中大于 \(S_r\) 的数的个数。所以:

\[ \sum_{r=1}^n \sum_{l=1}^r (S_r - S_{l-1}) \mathbin{\mathrm{mod}} M = \sum_{r=1}^N \left( S_r \times r - \sum_{l=1}^r S_{l-1} + M \times X_r \right). \]

那么问题就是对于 \(X_r\) 的维护,可以用权值线段数组,单调修改,区间查询。
要注意 \(S_i\) 可以等于 \(0\),所以要么加上偏移量,要么特判一下。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m;
ll a[N],b[N],c[N];
int lowbit(int x) 
{
    return x&-x;
}
void add(int k,int x)
{
    if(!k) return ;
    for(int i=k;i<=m;i+=lowbit(i)) c[i]+=x;
}
ll query(int k)
{
    ll ret=0;
    for(int i=k;i;i-=lowbit(i)) ret+=c[i];
    return ret;
}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i],b[i]=b[i-1]+a[i];
    for(int i=1;i<=n;i++) b[i]%=m;
    ll ans=0,s=0;
    for(int i=1;i<=n;i++)
    {
        ans+=b[i]*i-s+(query(m)-query(b[i]))*m;
        s+=b[i];
        add(b[i],1);
    }
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


F

先理解下题意,要满足条件,就是找到两个度数为 \(2\) 的点,这两个点的路径上全是度数为 \(3\) 的点,将这两个点连接即可。

那么考虑暴力查找,对于每个度数为 \(2\) 的点,找到另一个度数为 \(2\) 的点,只有下一个点度数为 \(3\) 才能走过去。显然这样的做法是 \(O(n^2)\) 的,也很容易被卡。

再进一步思考,将路径换成两点到最近公共祖先的路劲拼起来,而且最近公共祖先的度数必须是 \(3\)。那么就可以枚举所有度数为 \(3\) 的点作为根节点,搜索度数为 \(2\) 的点的个数 \(sum\),贡献就是 \(sum \times (sum-1)/2\),标记经过的所有度数为 \(3\) 的点,不用重复计算。

复杂度为 \(O(n)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
vector<int> g[N];
bool v[N];
int dfs(int x,int fa)
{
    int ret=0;
    v[x]=1;
    for(int i=0;i<g[x].size();i++)
    {
        int y=g[x][i];
        if(y==fa) continue;
        if(g[y].size()==2) ret++;
        else if(g[y].size()==3) ret+=dfs(y,x);
    }
    return ret;
}
void solve()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    ll ans=0;
    for(int i=1;i<=n;i++) 
    {
        if(g[i].size()==3&&!v[i])
        {
            ll x=dfs(i,0);
            ans+=x*(x-1)/2;
        }
    }
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

posted @ 2024-11-04 18:08  zhouruoheng  阅读(7)  评论(0编辑  收藏  举报