首页 > 其他分享 >AtCoder Beginner Contest 229(F,G)

AtCoder Beginner Contest 229(F,G)

时间:2023-06-23 19:22:40浏览次数:39  
标签:AtCoder Beginner int mid long maxn 229 include define

AtCoder Beginner Contest 229(F,G)

F(二部图,dp)

F

这个题大致是给你\(n+1\)个点,为\(0\)到\(n\),然后\(n\)条边是点\(0\)到\(1...n\)这些点的\(n\)条边,后面还有\(n\)条边,连接点\(i\)和\(i+1\)(其中\(i\)为\(1\)到\(n\),其中\(n\)是和\(1\)连接的)

前\(n\)条边的价值是\(a_i\),后面\(n\)条边的价值是\(b_i\),我们需要删除一些边,使得这个图变成一个二部图,其中删除每一条边的价值如上,问得到一个二部图的最小价值为多少

对于二部图,我的理解就是可以把一个图的点分成两个集合,两个集合的不同点可以互相相连,但是同一集合里面的点一定是不连通的

那么,对于这些点,我们也可以分成两个集合

设两个集合,编号为\(0\)和\(1\),我们先让点\(0\)在集合\(0\),然后对于其他的点,我们需要判断是否在一个集合,如果在同一个集合,那么需要删除相连的边,取较小的

我们可以从\(1\)到\(n\)一个一个的选择,但是,假如此时选择的是\(i\)的分配,我们只需要按照上一个进行判断即可了,但是还有一个边,就是点\(n\)和\(1\),那么第\(n\)的点的选择要删除的边不仅仅和\(n-1\)个点的关系,还需要和\(1\)的点的关系,所以,我们不仅需要知道最新点的选择,还需要知道第一个点的选择

\(dp[i] [x] [y]\)其中\(i\)是我们1到\(i\)的点都已经分配好了,其中点\(i\)在集合\(x\),而点\(1\)在集合\(y\)

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
#include <bitset>
#include <numeric>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define eps 1e-6
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=2e5+10;
const int mod=1e9+7;
int dp[maxn][2][2];
int n;
int a[maxn],b[maxn];
signed main ()
{
  cin>>n;
  for (int i=1;i<=n;i++)
  {
    cin>>a[i];
  }
  for (int i=1;i<=n;i++)
  {
    cin>>b[i];
  }
  for (int i=0;i<=n;i++)
  {
    for (int x=0;x<=1;x++)
    {
      for (int y=0;y<=1;y++)
      {
        dp[i][x][y]=inf;
      }
    }
  }
  dp[1][1][1]=0;
  dp[1][0][0]=a[1];
  for (int i=2;i<=n;i++)
  {
    dp[i][1][0]=min(dp[i-1][1][0]+b[i-1],dp[i-1][0][0]);//点i和点i-1在同一个集合,需要删除边
    dp[i][1][1]=min(dp[i-1][1][1]+b[i-1],dp[i-1][0][1]);
    dp[i][0][0]=min(dp[i-1][0][0]+b[i-1]+a[i],dp[i-1][1][0]+a[i]);//还要记得防止i和0在同一个集合
    dp[i][0][1]=min(dp[i-1][0][1]+b[i-1]+a[i],dp[i-1][1][1]+a[i]);
  }
  int ans=inf;
  for (int i=0;i<=1;i++)
  {
    for (int j=0;j<=1;j++)
    {
      if(i==j)
      {
        ans=min(ans,dp[n][i][j]+b[n]);
      }
      else 
      {
        ans=min(ans,dp[n][i][j]);
      }
    }
  }
  cout<<ans<<"\n";
  system ("pause");
  return 0;
}

G(字符串,二分)

G

这个题大意是给出一个字符串,里面的字符只有\(Y\)和\(.\)两种,我们最多可以交换位置\(i\)和\(i+1\)的字符\(k\)次,问我们可以得到的最长连续\(k\)的长度

类似于学校校赛的一道

我们可以把每一个我们需要的\(Y\)按顺序排起来需要交换的次数,记录在\(g\)数组里面

我们按照第一个\(Y\)在位置\(0\),第二个在位置\(1\),以此类推

我们每次选择让\(l\)到\(r\)这一区间的\(Y\)都放在一起,但是由于这些都可能没有在一起,贪心的想,可以让中间的那一个\(Y\)不需要动,它左边的往右边移动,它右边的往左边移动。

但是我们需要移动多少次呢

其实,我前面记录的每一个\(Y\)到相应位置的交换次数都是相对的,如果已经固定了一个应该要到的位置,不管到了哪个位置,最后相邻的都是\(Y\),那么要让\(x\)和\(y\)个\(Y\)距离合适(要么为\(1\),要么为\(2\)...),为\(g[y]-g[x]\)

然后对以区间\(l\)到\(r\)之间的\(Y\)都连在一起了,我们贪心的想,让中间位置的\(Y\)不动,按照前面的想法,在慢慢来写

具体可以这样计算

所以,我们还需要记录一下\(g\)的前缀和,然后再按照不同的长度进行二分,只要该长度每一个可以在\(k\)个操作内可以得到,那么就是可以

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
#include <bitset>
#include <numeric>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define eps 1e-6
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=2e5+10;
const int mod=1e9+7;
int g[maxn],sum[maxn];
int n,k;
string s;
int cnt;
int fun(int l,int r)
{
  int mid=(l+r)>>1;
  int cntl=mid-l;
  int cntr=r-mid;
  int ll=cntl*(g[mid])-(sum[mid]-sum[l]);//l到mid-1
  int rr=sum[r+1]-sum[mid+1]-cntr*g[mid];
  int res=ll+rr;
  return res;
}
bool check(int len)
{
  for (int i=0,j;i+len-1<cnt;i++)
  {
    int l=i;
    int r=l+len-1;
    if(r>=cnt) break;
    int now=fun(l,r);
    if(now<=k) return true;
  }
  return false;
}
signed main ()
{
  cin>>s>>k;
  n=s.size();
  s=" "+s;
  for (int i=1;i<=n;i++)
  {
    if(s[i]=='Y')
    {
      g[cnt]=i-cnt;
      cnt++;
    }
  }
  for (int i=1;i<=cnt;i++)
  {
    sum[i]=sum[i-1]+g[i-1];
  }
  int l=1,r=cnt;
  int ans=0;
  while (l<=r)
  {
    int mid=(l+r)>>1;
    if(check(mid))
    {
      ans=mid;
      l=mid+1;
    }
    else 
    {
      r=mid-1;
    }
  }
  cout<<ans<<"\n";
  system ("pause");
  return 0;
}

标签:AtCoder,Beginner,int,mid,long,maxn,229,include,define
From: https://www.cnblogs.com/righting/p/17499898.html

相关文章

  • AtCoder Beginner Contest(abc) 306
    A-Echo题目大意把一个字符串的每个字符输出两遍解题思路签到题不多嗦了;神秘代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;typedefpair<int,int>PII;constintN=1e6+10;intn,m;signedmain(){cin>>n;string......
  • AtCoder Regular Contest 162 F Montage
    洛谷传送门AtCoder传送门题目限制可以被改写成,如果\(A_{a,b}=A_{c,d}=1\),那么\(A_{a,d}=A_{c,b}=1\)。考虑删去空白的行和列,那么对于每个\(A_{a,b}=A_{c,d}=1\),矩形\((a,b),(c,d)\)中一定都是\(1\)。发现每一行只可能存在一个极长\(1\)区间。并......
  • AtCoder Regular Contest 162 E Strange Constraints
    洛谷传送门AtCoder传送门完全没有思路。但是其实不难的。设\(d_i\)为\(i\)在\(B\)中的出现次数,题目要求:\(\foralli\in[1,n],d_i\leA_i\);对于位置\(i\),\(d_j\leA_i\)的数\(j\)可以被放到\(B_i\)。考虑按照\(d_i\)从大到小dp。设\(f_{i,j,k}\)......
  • AtCoder Beginner Contest(abc) 304
    A-FirstPlayer题目大意顺时针给定一个序列,序列的元素由一个字符串和一个数字组成;我们需要从有最小数字的元素开始,顺时针遍历整个序列,并输出字符串;解题思路签到题不多嗦了;神秘代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;ty......
  • AtCoder Beginner Contest(abc) 300
    A-N-choicequestion题目大意从n个数里面找出a+b的结果解题思路签到题不多嗦了神秘代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;typedefpair<int,int>PII;constintN=310;intn;signedmain(){inta,b;cin>>n......
  • AtCoder Regular Contest 162
    A答案即后缀最小值个数。时间复杂度\(\mathcal{O}(n)\)。提交记录:Submission#42717665-AtCoderRegularContest162B发现操作不改变逆序对个数奇偶性。逆序对个数为奇数则无解;为偶数则可以直接模拟。时间复杂度\(\mathcal{O}(n^2)\)。提交记录:Submission#42718848......
  • AtCoder Beginner Contest 220 H Security Camera
    洛谷传送门AtCoder传送门看到数据范围猜复杂度是\(O(\text{poly}(n)2^{\frac{n}{2}})\),所以考虑折半。至少有一个端点被选不好算,考虑转成两个端点都被选,但是边数奇偶性与\(m\)相同。称编号\(<\frac{n}{2}\)的点为左点,编号\(\ge\frac{n}{2}\)的点为右点(点编号从\(0......
  • AtCoder Beginner Contest 306 题解 A - E
    A-Echo题目大意给定一个字符串,需要把它每个字符重复输出。解题思路可以读完整个字符串,也可以按照字符读一个输出两个。ACCode#include<iostream>#include<algorithm>#include<cstring>#include<numeric>#defineendl'\n'#defineiosios::sync_with_stdio(fals......
  • AtCoder ABC306 DEF
    D-PoisonousFull-Course(DP)题意现在有\(N\)道菜,高桥需要依次享用。第\(i\)道菜有两个属性\((X_i,Y_i)\),其意义是:若\(X_i=0\),则第\(i\)道菜是解毒的,其美味度为\(Y_i\);若\(X_i=1\),则第\(i\)道菜是有毒的,其美味度为\(Y_i\)。当高桥享用一道菜,他的状态变化如下:......
  • AtCoder Beginner Contest 306 G Return to 1
    洛谷传送门AtCoder传送门考虑若干个能被\(1\)到达且能到达\(1\)的环,设它们的环长分别为\(a_1,a_2,...,a_k\)。那么我们现在要每个环走若干遍,使得步数不含除\(2\)或\(5\)以外的质因子。设第\(i\)个环走\(x_i\)遍,那么其实就是要求\(\sum\limits_{i=1}^ka_i......