刷题记录(2)

[ABC307D] Mismatched Parentheses

题面翻译

Syx 有个长度为 N N N 的字符串 S S S,其中, S S S() 和小写字母组成,每一个 ) 都要与其左边的 ( 配成一对,并将它们与它们中间的部分删除。

最后请你输出操作后的 S S S

By Saint_ying_xtf

题目描述

英小文字および (, ) からなる長さ $ N $ の文字列 $ S $ が与えられます。
以下の操作を可能な限り繰り返したあとの $ S $ を出力してください。

  • $ S $ の連続部分文字列であって、最初の文字が ( かつ 最後の文字が ) かつ 最初と最後以外に () も含まないものを自由に $ 1 $ つ選び削除する

なお、操作を可能な限り繰り返したあとの $ S $ は操作の手順によらず一意に定まることが証明できます。

输入格式

入力は以下の形式で標準入力から与えられる。

$ N $ $ S $

输出格式

答えを出力せよ。

样例 #1

样例输入 #1

8
a(b(d))c

样例输出 #1

ac

样例 #2

样例输入 #2

5
a(b)(

样例输出 #2

a(

样例 #3

样例输入 #3

2
()

样例输出 #3


样例 #4

样例输入 #4

6
)))(((

样例输出 #4

)))(((

提示

制約

  • $ 1\ \leq\ N\ \leq\ 2\ \times\ 10^5 $
  • $ N $ は整数である
  • $ S $ は英小文字および (, ) からなる長さ $ N $ の文字列である

Sample Explanation 1

例えば、以下の手順により操作後の $ S $ が ac となります。 - $ S $ の $ 4 $ 文字目から $ 6 $ 文字目までからなる部分文字列 (d) を削除する。$ S $ は a(b)c となる。 - $ S $ の $ 2 $ 文字目から $ 4 $ 文字目までからなる部分文字列 (b) を削除する。$ S $ は ac となる。 - これ以上操作を行うことはできない。

Sample Explanation 3

操作後の $ S $ は空文字列になる可能性があります。

用栈写,也可以用数组模拟栈,我看了题解中不用栈的思路,大体上是用两个数组,一次循环,然后对括号匹配,记录的数组在原数组匹配到右括号时开始删除自己的元素,直到匹配到左括号,还得多删除一次,以便将自己的左括号删除。

#include <iostream>
#include <string.h>
#define max 200100

using namespace std;
char str[max],flag[max];
int main()
{
    int n;
    cin >> n;
    // getchar();
    for(int i = 0; i < n; i++)
    {
        cin >> str[i];
    }
    int cnt = 0;
    int cnt1 = 0;
    // for(int i = 0; i < n; i++)
    // {
        // if(str[i]!=0)
        // cout << str[i];
    // }

    for(int i = 0; i < n; i++)
    {
        flag[++cnt] = str[i];//先把输入的每个字符都存进去,注意是++cnt不是cnt++,先加再赋值
        // cout << flag[cnt] << endl;
        if(str[i] == '(')
        cnt1++;//记录左括号次数
        if(str[i] == ')')
        {   
            if(cnt1 != 0)//左括号存在的话
            {
                cnt1--;//右括号匹配一个左括号
                while(flag[cnt] != '(')
                cnt--;//当此时的记录数组不是左括号,则删除
                cnt--;//是左括号只删除一个
            }
        }
    }

    for(int i = 1; i <= cnt; i++)//因为是++cnt,第一位是1
    cout <<flag[i];
    return 0;
}

Bargaining Table

题面翻译

给定一个N*M的矩阵,1表示已经占用了,0表示没有被占用,求一个由0构成的矩阵,使其周长最大。
输入:N,M,矩阵
输出:最大周长

Translated by 稀神探女

题目描述

Bob wants to put a new bargaining table in his office. To do so he measured the office room thoroughly and drew its plan: Bob’s office room is a rectangular room $ n×m $ meters. Each square meter of the room is either occupied by some furniture, or free. A bargaining table is rectangular, and should be placed so, that its sides are parallel to the office walls. Bob doesn’t want to change or rearrange anything, that’s why all the squares that will be occupied by the table should be initially free. Bob wants the new table to sit as many people as possible, thus its perimeter should be maximal. Help Bob find out the maximum possible perimeter of a bargaining table for his office.

输入格式

The first line contains 2 space-separated numbers $ n $ and $ m $ ( $ 1<=n,m<=25 $ ) — the office room dimensions. Then there follow $ n $ lines with $ m $ characters 0 or 1 each. 0 stands for a free square meter of the office room. 1 stands for an occupied square meter. It’s guaranteed that at least one square meter in the room is free.

输出格式

Output one number — the maximum possible perimeter of a bargaining table for Bob’s office room.

样例 #1

样例输入 #1

3 3
000
010
000

样例输出 #1

8

样例 #2

样例输入 #2

5 4
1100
0000
0000
0000
0000

样例输出 #2

16

这题大概算是个暴力枚举吧,但是还是用了二维前缀和去统计0的个数,然后再算周长,用了四个for循环用来定位最大的面积请添加图片描述
还有四个while循环防止越界。

#include <iostream>
#define MAX 30
using namespace std;


//二维前缀和的变形
char Loc[MAX][MAX];
int main()
{
    int n,m;
    cin >> n >> m;
    
    for(int i  = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            cin>>Loc[i][j];//注意输入的时候没有空格,所以当成字符型,而不是整型
        }
    }

    int Max = -11111;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1;j <=m; j++)
        {
            for(int k = i; k <=n; k++)
            {
                for(int l = j; l <= m; l++)
                {
                    int Locx = i,Locy = j;
                    while(Locy < l && Loc[Locx][Locy] == '0')//碰到1时也会跳出循环从下一位开始
                    Locy++;//搜索0的个数
                    if(Locy != l)
                    break;//J++应该会等于l后停止while循环,如果不等于则说明越界了需要跳出循环
                    while(Locx < k && Loc[Locx][Locy] == '0')
                    Locx++;
                    if(Locx != k)
                    break;
                    while(Locy > j && Loc[Locx][Locy] == '0')
                    Locy--;
                    if(Locy != j)
                    break;
                    while(Locx > i && Loc[Locx][Locy] == '0')
                    Locx--;
                    if(Locx!=i)
                    break;

                    /*在内部的四个while循环中,程序根据元素的值来判断当前位置是否在矩形的边框上,若不满足边框条件则跳出循环。

若当前位置在矩形的边框上,则计算当前矩形的周长,并与Max进行比较,更新Max为较大值。*/

                    if(Max < 2*(k - i + 1 + l - j + 1))
                    {
                        Max = 2*(k - i + 1 + l - j + 1);
                        // cout << Max << endl;
                    }
                }
            }
        }
    }
    cout << Max << endl;
    return 0;
    
}

[ABC296C] Gap Existence

题面翻译

有一个长度为 n n n 的数组 a a a,给定一个数 x x x,确定是否存在一组 ( i , j ) (i,j) (i,j) 满足 a i − a j = x a_i-a_j=x aiaj=x

Translated by @Zealous_YH

题目描述

長さ $ N $ の数列 $ A=(A_1,\ldots,A_N) $ が与えられます。

$ 1\leq\ i,j\ \leq\ N $ である組 $ (i,j) $ であって、$ A_i-A_j=X $ となるものが存在するかどうか判定してください。

输入格式

入力は以下の形式で標準入力から与えられる。

$ N $ $ X $ $ A_1 $ $ \ldots $ $ A_N $

输出格式

$ 1\leq\ i,j\ \leq\ N $ である組 $ (i,j) $ であって、$ A_i-A_j=X $ となるものが存在するとき Yes、存在しないとき No と出力せよ。

样例 #1

样例输入 #1

6 5
3 1 4 1 5 9

样例输出 #1

Yes

样例 #2

样例输入 #2

6 -4
-2 -7 -1 -8 -2 -8

样例输出 #2

No

样例 #3

样例输入 #3

2 0
141421356 17320508

样例输出 #3

Yes

提示

制約

  • $ 2\ \leq\ N\ \leq\ 2\times\ 10^5 $
  • $ -109 \leq A_i \leq 109 $
  • $ -109 \leq X \leq 109 $
  • 入力は全て整数である

Sample Explanation 1

$ A_6-A_3=9-4=5 $ です。

Sample Explanation 2

$ A_i-A_j=-4 $ となる組 $ (i,j) $ は存在しません。

Sample Explanation 3

$ A_1-A_1=0 $ です。

折磨我两天的题目发现是输出没分大小写(不是洛谷的原题),Ai-Aj = x换个思路就是Aj+x在Ai中查找就好了,为了节省时间用的二分查找。

#include <iostream>
#include <algorithm>
#include <math.h>
#define max 201000
using namespace std;

int cnt[max];

int Search_Bin(int left,int right,int key)
{
    int l = left;
    int r = right;
    int mid;
    while (l <= r)
    {
        mid = l + ((r-l)>>1);
        if(cnt[mid] > key)
        {
            r = mid - 1;
        }
        if(cnt[mid] < key)
        {
            l = mid + 1;
        }
        if(cnt[mid] == key)
        {
            return 1;
        }
    }
    return 0;   
}
int main()
{
    int n,x;
    cin >> n >> x;
    for(int i = 1; i <= n; i++)
    {
        cin >> cnt[i];
    }

    if(x == 0)
    {
        cout <<"Yes" << endl;
        return 0;
    }
    x = abs(x);
    sort(cnt+1,cnt+n+1);

    int left,right;
    left = 1,right = n;
    
    for(int i = n; i > 0; i--)
    {
        if(Search_Bin(left,right,cnt[i]-x))
        {
            cout << "Yes" <<endl;
            return 0;
        }
    }

    cout <<"No"<<endl;
    return 0;
}

最大加权矩形

题目描述

为了更好的备战 NOIP2013,电脑组的几个女孩子 LYQ,ZSC,ZHQ 认为,我们不光需要机房,我们还需要运动,于是就决定找校长申请一块电脑组的课余运动场地,听说她们都是电脑组的高手,校长没有马上答应他们,而是先给她们出了一道数学题,并且告诉她们:你们能获得的运动场地的面积就是你们能找到的这个最大的数字。

校长先给他们一个 n × n n\times n n×n 矩阵。要求矩阵中最大加权矩形,即矩阵的每一个元素都有一权值,权值定义在整数集上。从中找一矩形,矩形大小无限制,是其中包含的所有元素的和最大 。矩阵的每个元素属于 [ − 127 , 127 ] [-127,127] [127,127] ,例如

 0 –2 –7  0 
 9  2 –6  2
-4  1 –4  1 
-1  8  0 –2

在左下角:

9  2
-4  1
-1  8

和为 15 15 15

几个女孩子有点犯难了,于是就找到了电脑组精打细算的 HZH,TZY 小朋友帮忙计算,但是遗憾的是他们的答案都不一样,涉及土地的事情我们可不能含糊,你能帮忙计算出校长所给的矩形中加权和最大的矩形吗?

输入格式

第一行: n n n,接下来是 n n n n n n 列的矩阵。

输出格式

最大矩形(子矩阵)的和。

样例 #1

样例输入 #1

4
0 -2 -7 0
 9 2 -6 2
-4 1 -4  1 
-1 8  0 -2

样例输出 #1

15

提示

1 ≤ n ≤ 120 1 \leq n\le 120 1n120

依然是二维前缀和,四个循环找,所以最坏的情况是O(N^4) ,还有种O(N^3)的写法,但是目前没学会。

#include <iostream>
#define max 125
using namespace std;

int Loc[max][max];
int cnt[max][max];
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            cin >> Loc[i][j];
            // getchar();
        }
    }
    if(n == 1)
    {
        cout << Loc[1][1];
        return 0;
    }

    for(int i = 1; i <=n; i++)
    {
        for(int j  = 1; j <= n;j++)
        {
            cnt[i][j] = cnt[i - 1][j] + cnt[i][j - 1] + Loc[i][j] - cnt[i-1][j-1];
        }
    }

    int Max = -10000;

    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            for(int k = i; k <= n; k++)
            {
                for(int l = j; l <= n; l++)
                {
                    if(Max < (cnt[k][l] - cnt[i-1][l] - cnt[k][j-1] + cnt[i-1][j-1]))
                    {
                        Max = (cnt[k][l] - cnt[i-1][l] - cnt[k][j-1] + cnt[i-1][j-1]);
                    }
                }
            }
        }
    }

    cout << Max << endl;
    return 0;
}

Sum in Binary Tree

题面翻译

简要题意

给定一棵根结点为 1 1 1 的完全二叉树,编号为 x x x 的节点的左儿子编号为 x x x × \times × 2 2 2,右儿子编号为 x x x × \times × 2 2 2 + + + 1 1 1。从编号为 1 1 1 的点到编号为 n n n 的点的路径上的结点编号之和为多少?

题目描述

Vanya really likes math. One day when he was solving another math problem, he came up with an interesting tree. This tree is built as follows.

Initially, the tree has only one vertex with the number $ 1 $ — the root of the tree. Then, Vanya adds two children to it, assigning them consecutive numbers — $ 2 $ and $ 3 $ , respectively. After that, he will add children to the vertices in increasing order of their numbers, starting from $ 2 $ , assigning their children the minimum unused indices. As a result, Vanya will have an infinite tree with the root in the vertex $ 1 $ , where each vertex will have exactly two children, and the vertex numbers will be arranged sequentially by layers.

Part of Vanya’s tree.Vanya wondered what the sum of the vertex numbers on the path from the vertex with number $ 1 $ to the vertex with number $ n $ in such a tree is equal to. Since Vanya doesn’t like counting, he asked you to help him find this sum.

输入格式

The first line contains a single integer $ t $ ( $ 1 \le t \le 10^4 $ ) — the number of test cases.

This is followed by $ t $ lines — the description of the test cases. Each line contains one integer $ n $ ( $ 1 \le n \le 10^{16} $ ) — the number of vertex for which Vanya wants to count the sum of vertex numbers on the path from the root to that vertex.

输出格式

For each test case, print one integer — the desired sum.

样例 #1

样例输入 #1

6
3
10
37
1
10000000000000000
15

样例输出 #1

4
18
71
1
19999999999999980
26

提示

In the first test case of example on the path from the root to the vertex $ 3 $ there are two vertices $ 1 $ and $ 3 $ , their sum equals $ 4 $ .

In the second test case of example on the path from the root to the vertex with number $ 10 $ there are vertices $ 1 $ , $ 2 $ , $ 5 $ , $ 10 $ , sum of their numbers equals $ 1+2+5+10 = 18 $ .
根据二叉树的性质,左子树等于父节点的二倍,右子树等于父节点的二倍加一就可以算出来,记得加上根节点的值。

#include <iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        int t;
        int sum = 0;
        cin >> t;
        if(t == 1)
        {
            cout << "1" << endl;
        }else{
            while(t != 1)
            {
                if(t % 2 == 0)
                {
                    sum += t;
                    t /= 2;
                }else{
                    sum += t;
                    t-=1;
                    t /= 2;
                }
            }
            cout << sum << endl;
        }
    }
    return 0;
}

A+B Problem(高精)

题目描述

高精度加法,相当于 a+b problem,不用考虑负数

输入格式

分两行输入。 a , b ≤ 1 0 500 a,b \leq 10^{500} a,b10500

输出格式

输出只有一行,代表 a + b a+b a+b 的值。

样例 #1

样例输入 #1

1
1

样例输出 #1

2

样例 #2

样例输入 #2

1001
9099

样例输出 #2

10100

高精度运算,用char型数组,记得进位操作和相加是分开的。

#include <iostream>
#include <string.h>
using namespace std;

char a[501],b[501];
int A[501],B[501],C[502];

int main()
{
    scanf("%s",a);
    getchar();
    scanf("%s",b);
    int Lena = strlen(a);
    int Lenb = strlen(b);

    int i,j;
    for(j = Lena - 1,i = 0; i < Lena; i++)
    {
        A[i] = a[j--] - 48;
        // cout<< "A is:" << A[i] << endl;
    }
    for(j = Lenb - 1,i = 0; i < Lenb; i++)
    {
        B[i] = b[j--] - 48;
        // cout<< "B is:" << B[i] << endl;
    }

    // cout << "This is a grand Line:" << endl;
    // cout << "---------------------" << endl;
    int max = Lena;
    if(Lena < Lenb)
    max = Lenb;

    for(i = 0; i < max; i++)
    {
        C[i] = A[i] + B[i];   
        // cout << "A puls B is:" << C[i] << endl;
    }

    for(i = 0; i < max + 1; i++)
    {
        if(C[i] > 9)
        {
            C[i+1]++;
            C[i] -= 10;
        }
    }
    int cnt;
    for(i = max + 1; i>=0; i--)
    {
        // cout << i << endl;
        if(C[i] != 0)
        {

            cnt = i;
            break;
        }
    }
    for(i = cnt; i >= 0; i--)
    cout << C[i];
    return 0;
}

本周任务完成哩!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值