首页 > 其他分享 >【刷题笔记】2019 CSP-S

【刷题笔记】2019 CSP-S

时间:2024-09-23 22:24:03浏览次数:15  
标签:ch int sum st 括号 2019 maxn CSP 刷题

2019 CSP-S 题目整理

A-格雷数

思路简介


思路很简单,如果编号在中点的左边那么就输出0,否则输出1,同时还要改变编号。

代码实现


#include<bits/stdc++.h>
#define maxn 80
using namespace std;
typedef __int128 int1;
int1 n,k;
__int128 read(){
	char ch=getchar();
	__int128 s=0,f=1;
	while(ch>'9'||ch<'0'){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0'){
		s=(s<<3)+(s<<1)+ch-'0';
		ch=getchar();
	}
	return s*f;
}
void dfs(int cur,int1 x){//cur位,x号
    int1 mid=(int1)pow(2,cur-1)-1;
    //cout<<cur<<' '<<mid<<' '<<x<<endl;
    if(cur==1){
        if(x==0)cout<<0;
        else if(x==1)cout<<1;
        return;
    }
    if(x<=mid){
        cout<<0;
        dfs(cur-1,x);
    }
    else {
        cout<<1;
        dfs(cur-1,(int1)pow(2,cur)-x-1);
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    n=read();k=read();
    //cout<<k<<endl;
    dfs(n,k);
    return 0;
}

——int128


这道题数据给的太毒瘤,\(2^{64}-1\),卡着\(unsigned\ long\ long\)的范围,稍微超过一点就要溢出,所以还是开\(\_int128\)大大的好
因此读入必须使用快读

_int rd(){
    _int f=1,sum=0;
    char ch;
    ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0'){
        sum=(sum<<3)+(sum<<1)+ch-'0';
        ch=getchar();
    }
    return sum*f;

输出必须使用快写

void write(_int n){
    if(n<0)putchar('-'),n=-n;
    if(n>9)write(n/10);
    putchar(n%10+'0');
}

B-括号树

题目大意


有一棵树,树上的每个节点是半个括号,要求从树根1到节点\(i\),路径上经过的完全不同的合法子串的个数。
题目中对合法括号串的定义如下:
1.() 是合法括号串。
2.如果 A 是合法括号串,则 (A) 是合法括号串。
3.如果 A,B 是合法括号串,则 AB 是合法括号串。

思路简介


设\(sum[i]\)表示从1到节点\(i\)路径上经过的合法子串个数,\(f[i]\)表示第\(i\)个节点对答案的贡献。
来看下面这个例子

\[()((()()))() \]

括号串的中间部分是四个相包含的括号,在与另外两个括号组合时他等价于1个括号,所以

\[(A)=() \]

简化完括号串以后,再来分析。对于

\[A(B)=A() \]

右括号对于答案的贡献一定为对应左括号上一个字符的贡献+1,因为多了去本身的一种方案,即

\[f[x]=f[fa[t]]+1 \]

注意!!在深搜时如果往栈里压进数,在回溯时要弹出;在深搜时如果弹出数,在回溯时要压回栈里。

代码实现


#include<bits/stdc++.h>
#define maxn 500010
#define ll long long
using namespace std;
struct edge{
    int to,next;
}e[maxn];
int n;
int cnt=0,fa[maxn],head[maxn];
char ch[maxn];
ll f[maxn],sum[maxn],ans=0;
stack<int>st;
void add(int x,int y){
    e[++cnt].next=head[x];
    e[cnt].to=y;
    head[x]=cnt;
}
void write(ll x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	return;
}
void dfs(int u){
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to,cur=-1;
        if(ch[v]=='('){
           st.push(v);     
        }
        else if(ch[v]==')'){
            if(!st.empty()){
                cur=st.top();
                f[v]=f[fa[cur]]+1;
                st.pop();
            }
        }
        sum[v]=sum[u]+f[v];
        dfs(v);
        if(cur!=-1)st.push(cur);
        else if(!st.empty())st.pop();
    }
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){
        ch[i]=getchar();
        while(ch[i]!='('&&ch[i]!=')'){
            ch[i]=getchar();
        }
    }
    add(0,1);
    for(int i=1;i<n;i++){
        int x,y=i+1;
        cin>>x;
        add(x,y);
        fa[y]=x;
    }
    dfs(0);
    for(int i=1;i<=n;i++){
        ans^=i*sum[i];
        //cout<<sum[i]<<' ';
    }
    write(ans);
    return 0;
}

标签:ch,int,sum,st,括号,2019,maxn,CSP,刷题
From: https://www.cnblogs.com/GSNforces/p/18428043

相关文章

  • [赛记] csp-s模拟3
    奇观55pts赛时打的$\Theta(n^5)$和$m=0$的特殊性质拿了55pts;考虑正解,首先,$CCF$这三个字母是可以分开维护的;对于$C$,其可以看作一个连了四个点的线段,对于$F$,其可以看作一个连了三个点的线段在再最后分别多连两个点;设$f_{i,j}$表示维护一个连了$i$......
  • leetcode刷题day27|贪心算法Part01(455.分发饼干、376. 摆动序列、53. 最大子序和)
    前言:贪心的本质选择每一阶段的局部最优,从而达到全局最优。455.分发饼干思路:局部最优-大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个;全局最优:喂饱尽可能多的小孩。可以尝试使用贪心策略,先将饼干数组和小孩数组排序,然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计......
  • 打卡信奥刷题(784)用Scratch图形化工具信P6488[普及组/提高组] [COCI2010-2011#6] OKUPL
    [COCI2010-2011#6]OKUPLJANJE题目描述一场巨大的派对结束以后,有五家报纸刊登了参加这场派对的人数,然而这些报纸上的数字可能是错误的。现在你知道整个会场的面积是LL......