AtCoder Beginner Contest 428

C - Brackets Stack Query

题目大意

一个字符串 T 被称为好的括号序列,当且仅当它满足以下条件:

  • T 可以通过对以下操作进行零次或多次连续执行以得到空字符串:
  • 选择一个作为连续子串的 (),并将其删除。

例如,()(()()) 和空字符串都是好的括号序列,但 )()())) 则不是好的括号序列。

有一个字符串 S。初始时,S 是一个空字符串。
请按顺序处理 Q 个查询,在每次查询之后,判断 S 是否是一个好的括号序列。

查询共有两种类型:

  • 1 c:给出一个字符 cc 一定是 () 中的一个。将 c 添加到 S 的末尾。
  • 2:删除 S 最后一个字符。保证此时 S 不是空字符串。

题目标签

括号序列

题解

括号序列的一个性质:将 ( 视为 1) 视为 -1,则对于一个好的括号序列,其前缀和时时刻刻不会小于 0,且最终前缀和为 0

维护当前字符串的前缀和即可得到是否存在前缀和小于 0 的情况,以及当前字符串的前缀和是否为 0

#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int q;
    cin>>q;
    int cnt_n=0,pre=0;//统计前缀为负数的个数,前缀和
    vector<int> tmp;
    while(q--){
        int op;
        cin>>op;
        if(op==1){
            char c;
            cin>>c;
            if(c=='('){
                pre++;
                tmp.push_back(1);
            }
            else{
                pre--;
                tmp.push_back(-1);
            }
            if(pre<0) cnt_n++;
        }
        else{
            int c=tmp.back();
            tmp.pop_back();
            if(c==-1){
                if(pre<0) cnt_n--;
                pre++;
            }
            else{
                if(pre<0) cnt_n--;
                pre--;
            }
        }
        cout<<((cnt_n||pre!=0)?"No\n":"Yes\n");
    }
    return 0;
}

D - 183184

题目大意

对于正整数 xy,定义函数 f(x,y) 如下:

  • xy 以十进制表示的字符串形式按顺序拼接,得到字符串 z,将 z 作为十进制整数的值即为 f(x,y)

例如,f(3,14)=314f(100,3)=1003

现给出正整数 CD,请找出满足以下条件的整数 x 的个数:

  • 1 \leq x \leq D
  • f(C, C+x) 是一个完全平方数。

你需处理 T 组测试数据,对每组数据都输出对应的答案。

题解

N^2 = f(C, C+x),且 C+x 的位数为 i,则有:

N^2 = C \times 10^i + (C+x) = C(10^i + 1) + x

由于 C+x 的位数为 i,故 C+x 的取值范围为:

[10^{i-1}, 10^i-1]

x 的取值范围为:

[10^{i-1}-C, 10^i-1-C]

x_l = \max(1, 10^{i-1}-C)x_r = \min(D, 10^i-1-C),则 N^2 的取值范围为:

[C(10^i + 1) + x_l, C(10^i + 1) + x_r]

N 的可行方案数即 [C(10^i + 1) + x_l, C(10^i + 1) + x_r] 内完全平方数的个数,即 [\lceil \sqrt{C(10^i + 1) + x_l} \rceil, \lfloor \sqrt{C(10^i + 1) + x_r} \rfloor] 内整数的个数。

参考代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
int qpow(int b,int p){
    int res=1;
    while(p){
        if(p&1) res=res*b;
        b=b*b;
        p>>=1;
    }
    return res;
}
int cal(int x){
    int bit=0;
    while(x){
        x/=10;
        bit++;
    }
    return bit;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        int c,d;
        cin>>c>>d;
        int l=cal(c+1),r=cal(c+d);
        int ans=0;
        for(int i=l;i<=r;i++){
            int xl=max(qpow(10,i-1)-c,(long long)1);
            int xr=min(qpow(10,i)-c-1,d);
            int fl=ceill(sqrt((long double)xl+c*(qpow(10,i)+1)));
            int fr=floorl(sqrt((long double)xr+c*(qpow(10,i)+1)));
            ans+=max((long long)0,fr-fl+1);
        } 
        cout<<ans<<'\n';
    }
    return 0;
}

E - Farthest Vertex

题目大意

给定一棵包含 N 个顶点的树,顶点编号为 1N。第 i 条边连接顶点 A_iB_i
定义两个顶点 uv 之间的距离为连接这两个顶点的唯一简单路径上的边的数量。(这样的路径是唯一的。)

题解

树的直径的经典性质:对于任意结点 u,距离 u 最远的结点 v 一定是任意一条树的直径的一个端点。

故求出编号最大的两个直径端点 xy,对于每个结点 i,若:

  • \text{dis}(x, i) > \text{dis}(y, i),则输出 x
  • \text{dis}(x, i) < \text{dis}(y, i),则输出 y
  • \text{dis}(x, i) = \text{dis}(y, i),则输出 \max(x, y)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int h[N],ne[N<<1],to[N<<1],idx=0;
void add(int a,int b){
    to[++idx]=b;
    ne[idx]=h[a];
    h[a]=idx;
}
int dis1[N],dis2[N];
void dfs(int u,int fa){
    for(int i=h[u];~i;i=ne[i]){
        int v=to[i];
        if(v==fa) continue ;
        dis1[v]=dis1[u]+1;
        dfs(v,u);
    }
}
void dfs2(int u,int fa){
    for(int i=h[u];~i;i=ne[i]){
        int v=to[i];
        if(v==fa) continue ;
        dis2[v]=dis2[u]+1;
        dfs2(v,u);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) h[i]=-1;
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        add(u,v),add(v,u);
    }
    dfs(1,0);
    int sta=0,ed=0;
    int mx_d=0;
    for(int i=1;i<=n;i++)
        if(dis1[i]>=mx_d){
            sta=i;
            mx_d=dis1[i];
        }
    dis1[sta]=0;
    dfs(sta,0);
    for(int i=1;i<=n;i++)
        if(dis1[i]>=mx_d){
            ed=i;
            mx_d=dis1[i];
        }
    dfs2(ed,0);
    for(int i=1;i<=n;i++){
        if(dis1[i]>dis2[i]) cout<<sta<<'\n';
        else if(dis1[i]<dis2[i]) cout<<ed<<'\n';
        else cout<<max(ed,sta)<<'\n';
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容