首页 > 其他分享 >AtCoder Beginner Contest 247(E,F)

AtCoder Beginner Contest 247(E,F)

时间:2023-04-10 20:11:08浏览次数:41  
标签:AtCoder const Beginner ty int 247 maxn include dp

AtCoder Beginner Contest 247(E,F)

E(思维)

E

这个题大意就是给一个长度为\(n\)的数组,一个\(x\)和一个\(y\),问这个数组里面可以找到多少段\([l,r]\)满足这一段里面的最大值是\(x\),最小值是\(y\)

这里的做法是固定最右端,寻找最左端的可能的数量,最后相加

对于每一个位置,都有作为最右端的可能,那么对于一个点\(i\),我们可以去寻找这个最左端的范围

对于这一个范围的最左端就是离\(i\)最近的一个不满足条件的位置(大于最大值或者是小于最小值),最右端就是从\(1\)到\(i\)以来,我们最后一次找到最大值的位置和最小值的位置的较小的那一个(这样从\(min(posx,posy)\)到\(i\),至少存在一个最大值和最小值)

只要存在满足这个范围的最左端,我们就加上去\(res=res+r-l\)

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <bitset>
#include <unordered_map>
using namespace std;
const int maxn=2e5+10;
const int mod=998244353;
const double eps=1e-12;
#define int long long 
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
signed main ()
{
    int ans=0;
    int n,x,y;
    cin>>n>>x>>y;
    int pre=0;
    int posx=0,posy=0;
    for (int i=1;i<=n;i++)
    {
        int now;
        cin>>now;
        if(now>x||now<y) pre=i;
        if(now==x) posx=i;
        if(now==y) posy=i;
        int r=min(posx,posy);
        if(r>pre)
        {
            ans+=r-pre;
        }
    }
    cout<<ans<<"\n";
    system ("pause");
    return 0;
}

F(dp)

F

这个题的大意就是有\(n\)张牌,每一张牌都有两个数\(p\)和\(q\),\(P\)=\(1,2,3,...n\),\(Q\)=\(1,2,3,...n\).

我们需要选择任意张牌,只要这些牌里面的数存在\(1\)到\(n\)的数即可,问有多少种选择,可以满足以上条件

对于一张牌,可能存在两个不同的数,可以把两个数连在一起,我们把这些连在一次的那些数,我们可以把这些数看做一个整体,因为这些数字都存在两个,所以我们允许某些数只出现一个,所以我们要进行一次\(dp\)

dp[i][1][1]//对于i个数,dp[i][1][0]和dp[i][0][1]只存在一个
//对于只有一个数,只存在dp[1][1][1]=1,dp[1][0][0]=1,1个数在一张牌上
    dp[1][1][1]=1,dp[1][0][0]=1;
for (int i=2;i<=n;i++)
{
    for (int j=0;j<=1;j++)
    {
        dp[i][j][0]=dp[i-1][j][1];//这一个如果不选择,就需要依靠另外一张牌上的这一个数了
        dp[i][j][1]=(dp[i-1][j][0]+dp[i-1][j][1])%mod;//选择的话,上一张有和没有都没有什么关系,都可以
    }
    ans[i]=(dp[i][0][1]+dp[i][1][0]+dp[i][1][1])%mod;//保证前i个都存在
}

对于每一种环,都会包括\(cnt\)个数,那么这\(cnt\)个数需要\(ans[cnt]\)种选择可以让这\(cnt\)个数都存在

对于每一部分,用乘法计算

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <bitset>
#include <unordered_map>
using namespace std;
const int maxn=2e5+10;
const int mod= 998244353;
const double eps=1e-12;
#define int long long 
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
int n,p[maxn],q[maxn];
int f[maxn];
int siz[maxn];
int ans[maxn];
int dp[maxn][2][2];
int find(int x)
{
    if(x==f[x]) return f[x];
    return f[x]=find(f[x]);
}
void merge(int x,int y)
{
    int tx=find(x);
    int ty=find(y);
    if(tx==ty) return ;
    siz[tx]+=siz[ty];
    siz[ty]=0;
    f[ty]=tx;
    return ;
}
void init()
{
    dp[1][1][1]=1;
    dp[1][0][0]=1;
    ans[1]=1;
    for (int i=2;i<=n;i++)
    {
        for (int j=0;j<=1;j++)
        {
            dp[i][j][0]=dp[i-1][j][1];
            dp[i][j][1]=(dp[i-1][j][1]+dp[i-1][j][0])%mod;
        }
        ans[i]=(dp[i][1][1]+dp[i][1][0]+dp[i][0][1])%mod;
    }
    return ;
}
signed main ()
{
    cin>>n;
    init();
    for (int i=1;i<=n;i++)
    {
        f[i]=i;
        siz[i]=1;
        cin>>p[i];
    }
    for (int i=1;i<=n;i++)
    {
        cin>>q[i];
        merge(p[i],q[i]);
    }
    int res=1;
    for (int i=1;i<=n;i++)
    {
        if(find(i)==i)
        {
           // cout<<siz[i]<<"\n";
            res=(res*ans[siz[i]])%mod;
        }
    }
    cout<<res<<"\n";
    system ("pause");
    return 0;
}

标签:AtCoder,const,Beginner,ty,int,247,maxn,include,dp
From: https://www.cnblogs.com/righting/p/17304146.html

相关文章

  • AtCoder Regular Contest 127
    D-LIS2难搞的地方在于取min,考虑比较\((a_i\oplusa_j,b_i\oplusb_j)\)两者的过程:是在它们第一位不一样的地方比较,取该位为0的那个。而判断两个数在某位是否相等,可以想到异或操作,然后把这两者异或起来后,由异或运算的交换律可得等价于\((a_i\oplusb_i)\oplus(a_j\oplus......
  • AtCoder Regular Contest 159
    Preface这周六紧张刺激的一日三赛,上午蓝桥杯,晚上ARC之后隔5min就是CF,可谓是手搓键盘到冒烟的一天了这场其实打的感觉很没水准,B刚开始没想清楚很多边界条件挂了三发,45min左右才过然后C的构造也不太会,随便写了个暴力也是挂挂挂,只好弃了去写D题了结果发现D题好像是个不难的线段树......
  • 练习记录- AtCoder Beginner Contest 295(D)
    vp的觉得我的D很聪明所以来写一下(乐D-ThreeDaysAgo题意就是求所有字符出现次数均为偶数的字串数量太笨了所以想了很久我把存在奇数个1当作第2位是2那么当经过了两次1 2^2这个2就变成了02就是第二位就是4...以此类推 所以我遍历一遍字符串求出当前的异或......
  • 练习记录-AtCoder Beginner Contest 296(A-F)
    vp的感觉整场挺智慧A-Alternately找有没有连续的男女#include<bits/stdc++.h>#defineclosestd::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)usingnamespacestd;typedeflonglongll;constllMAXN=3e5+7;constllmod=1e9+7;constllinf=0x3......
  • 1247. 交换字符使得字符串相同
    题目链接:[1247.交换字符使得字符串相同]方法:找规律解题思路由于只能两个字符串之间交换字符,单个字符串内不允许交换,因此如果只有一个字符对不相同,那么一定无法通过交换变为相同字符串,同理当不相同的字符对为奇数时,也无法通过交换变为相同字符。当不相同的字符对数为偶数时,现......
  • AtCoder Beginner Contest 278
    口胡一下,从青色开始E-GridFilling给定一个W×H的矩阵,每个格子有一个数,在1和N之间,给定w<=W,h<=H,对于每个满足1<=i<=W-w+1,1<=j<=H-h+1的格子(i,j),求以它为左上角的w×h矩阵被遮住后整个大矩阵还剩下几种数字。W,H,N,w,h<=300首先我们看见这个熟悉的300就知道是立方算法又注......
  • AtCoder ABC286 C - Chinese Restaurant
    AtCoderABC286C-ChineseRestaurant题目描述有\(N\)个人从\(0\)开始编号,按逆时针顺序间隔均匀地坐在转盘周围。在开始时,第\(p_i\)盘菜在第\(i\)个人的前面。现在,你可以进行以下操作\(0\)次或多次。将转盘逆时针旋转\(\dfrac{1}{N}\)圈。也就是说,旋转前......
  • AtCoder ABC295 D - Three Days Ago
    AtCoderABC295D-ThreeDaysAgo题目描述给出一个数字串,问有多少子段满足,可以以某种方式将这个子段重排,将子段分成两个完全相同的部分。样例输入输出202303224\((1,6)(1,8)(2,7)(7,8)\)都可以满足条件分析如果要满足某一个字段可以被分为两个相同的部分,则不......
  • AtCoder ABC294 F - Sugar Water 2
    AtCoderABC294F-SugarWater2题意有\(2\)排糖和水。第\(1\)排有\(N\)瓶糖和\(N\)瓶水。糖分别有\(A_i\)克,水分别有\(B_i\)克。第\(2\)排有\(M\)瓶糖和\(M\)瓶水,糖分别有\(C_i\)克,水分别有\(D_i\)克。若要从第\(1\)排糖水中找到\(A_i\)克糖和......
  • AtCoder Beginner Contest 226(E,F,G)
    AtCoderBeginnerContest226(E,F,G)E(并查集)E这个题的大意是给我们一个无向图,我们可以把这些无向边变成有向边,让每一个点的入度都是\(1\),问有多少种变化方式要让有\(x\)个点的无向图,形成一棵树的边的数量是\(x-1\),但是我们需要的是每一个点的入度为\(1\),那么我们只还需要一条......