Codeforces Round #576 (Div. 2)

22 篇文章 0 订阅
15 篇文章 0 订阅

A

扫一遍就好了n*14

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int N = 1000010;
inline int read()
{
  int p=0,f=1; char ch=getchar();
  while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
  while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
  return p*f;
}
int a[N];
 
int main()
{
  // freopen("a.in","r",stdin);
  int n = read(); int x = read(); int y = read(); int s = 0;
  for(int i=1;i<=n;i++) a[i] = read();
  for(int i=1;i<=n;i++)
  {
    bool bk = 1;
    for(int j=max(i-x,1);j<=min(n,i+y);j++) if(a[i] > a[j]) bk=0;
    if(bk){printf("%d\n",i); break;}
  }
  
  return 0;
}

B

勾股定理推式子

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int N = 1000010;
inline int read()
{
  int p=0,f=1; char ch=getchar();
  while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
  while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
  return p*f;
}
int main()
{
  // freopen("a.in","r",stdin);
  double h = read(); double l = read(); 
  return printf("%.13lf\n",(l*l-h*h)/(2*h)),0;
}

C

读懂题意,把所有不同的数字排个序,然后两个指针扫就好了

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int N = 1000010;
inline int read()
{
  int p=0,f=1; char ch=getchar();
  while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
  while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
  return p*f;
}
int a[N],sum[N];
int main()
{
  // freopen("a.in","r",stdin);
  int n = read(); int I = read();
  for(int i=1;i<=n;i++) a[i] = read();
  sort(a+1,a+n+1); int s = 0;
  for(int i=1;i<=n;i++) if(a[i] != a[i-1]) s++,sum[i] = sum[i-1] + 1; else sum[i] = sum[i-1];
  int mk = 8 * I / n;
  int p = 1;
  for(int i=1;i<=mk;i++){p=p*2; if(p >= s){printf("0\n"); return 0;} }
  int r=1; int mn = n; //printf("%d\n",p);
  //for(int i=1;i<=n;i++) printf("%d ",sum[i]); printf("\n");
  for(int l=1;l<=n;l++)
  {
    while(sum[r+1] - sum[l] +1<= p && r<n){r++;}
    // printf("%d %d\n",l,r);
    mn = min(mn , n-(r-l+1));
  }
  return printf("%d\n",mn),0;
}

D

直接线段树区间标记单点修改就好了

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int N = 1000010;
inline int read()
{
  int p=0,f=1; char ch=getchar();
  while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
  while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
  return p*f;
}
int a[N],n; int lc[N<<2],rc[N<<2],rt,tot,c[N<<2],lazy[N<<2];
void push_down(int u,int L,int R)
{
  if(lazy[u] == -1) return ;
  int x = lazy[u]; lazy[u] = -1;
  int mid=(L+R)>>1;
  if(c[lc[u]] < x)
  {
    c[lc[u]] = x; lazy[lc[u]] = x;
  }
  if(c[rc[u]] < x)
  {
    c[rc[u]] = x; lazy[rc[u]] = x;
  }
}
void link(int &u,int L,int R,int k,int x)
{
  if(!u) u=++tot,lazy[u] = -1;
  if(L==R){c[u] = x; return ;}
  push_down(u,L,R);
  int mid=(L+R)>>1;
  if(k<=mid) link(lc[u],L,mid,k,x);
  else link(rc[u],mid+1,R,k,x);
  c[u] = min(c[lc[u]] , c[rc[u]]);
}
void chg(int u,int L,int R,int l,int r,int x)
{
  if(L==l && R==r)
  {
    if(c[u] < x) lazy[u] = x,c[u] = x;
    return ;
  }
  push_down(u,L,R);
  int mid=(L+R)>>1;
  if(r<=mid) chg(lc[u],L,mid,l,r,x);
  else if(l>mid) chg(rc[u],mid+1,R,l,r,x);
  else
  {
    chg(lc[u],L,mid,l,mid,x);
    chg(rc[u],mid+1,R,mid+1,r,x);
  }
  c[u] = min(c[lc[u]] , c[rc[u]]);
}
void find(int u,int L,int R)
{
  if(L==R){printf("%d%c",c[u]," \n"[L==n]); return ;}
  int mid=(L+R)>>1;
  push_down(u,L,R);
  find(lc[u],L,mid);
  find(rc[u],mid+1,R);
}
int main()
{
  n = read();
  for(int i=1;i<=n;i++) a[i] = read();
  rt=tot=0; for(int i=1;i<=n;i++) link(rt,1,n,i,a[i]);
  int m = read();
  for(int i=1;i<=m;i++)
  {
    int op = read();
    if(op==1)
    {
      int p = read(); int x = read();
      link(rt,1,n,p,x);
    }
    else if(op == 2)
    {
      int x = read();
      chg(rt,1,n,1,n,x);
    }
  }
  
  find(rt,1,n);
  
  return 0;
}

E

有边能匹配就加,不行就不管,不能N次匹配必定有大小为N的独立集

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int N =6000010;
int match[N]; int l = 0; bool v[N];
int main()
{
  ios::sync_with_stdio(false);
  int T,n,m,x,y; cin >> T;
  while(T--)
  {
    cin >> n >> m; l = 0;
    rep(i,1,m)
    {
      cin >> x >> y;
      if(!v[x] && !v[y] && l<n){match[++l] = i; v[x] = 1; v[y] = 1;}
    }
    if(l==n){printf("Matching\n"); rep(i,1,l) printf("%d%c",match[i]," \n"[i==l]);}
    else{printf("IndSet\n"); int s = 0; rep(i,1,3*n) if(!v[i]){s++; printf("%d%c",i," \n"[s==n]); if(s==n) break;}}
    rep(i,1,3*n) v[i] = 0;
  }
  return 0;
}

F

N^5暴力,固定左上角和右下角dp 然后如果满直接搞掉,空也搞掉,考虑最好肯定是正方形
考虑如果一个正方形里面如果最优不是整个框起来,那么肯定有一行或者一列是空的
递归dp就好了

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int N = 55;
int r[N][N],c[N][N],s[N][N],f[N][N][N][N],n;
int sol(int x1,int y1,int x2,int y2)
{
  if(x1 <= 0 || x2<=0 || y1<=0 || y2<=0 || x1>n || x2>n || y1>n || y2>n || x1>x2 || y1>y2) return 0;
  // printf("%d %d %d %d\n",x1,y1,x2,y2);
  if(f[x1][y1][x2][y2]>=0) return f[x1][y1][x2][y2];
  
  if(s[x2][y2] + s[x1-1][y1-1] - s[x2][y1-1] - s[x1-1][y2] == (y2-y1+1) * (x2-x1+1))
    return f[x1][y1][x2][y2] = max(x2-x1+1,y2-y1+1);
  if(s[x2][y2] + s[x1-1][y1-1] - s[x2][y1-1] - s[x1-1][y2] == 0)
    return f[x1][y1][x2][y2] = 0;
  int ans = max(x2-x1+1,y2-y1+1);

  // printf("%d\n",ans);

  for(int i=x1;i<=x2;i++)
  {
    if(r[i][y2] - r[i][y1-1] == 0) ans = min(ans , sol(x1,y1,i-1,y2) + sol(i+1,y1,x2,y2));
  }
  for(int j=y1;j<=y2;j++)
  {
    if(c[x2][j] - c[x1-1][j] == 0) ans = min(ans , sol(x1,y1,x2,j-1) + sol(x1,j+1,x2,y2));
  }return f[x1][y1][x2][y2] = ans;
}
int main()
{
  cin >> n;
  rep(i,1,n) rep(j,1,n)
  {
    char ch; cin >> ch;
    // printf("!%c!",ch);
    if(ch=='#') s[i][j] = 1;
  }
  rep(i,1,n) rep(j,1,n) r[i][j] = r[i][j-1] + s[i][j];
  rep(i,1,n) rep(j,1,n) c[i][j] = c[i-1][j] + s[i][j];
  rep(i,1,n) rep(j,1,n) s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1];
  // rep(i,1,n){rep(j,1,n) printf("%d:%d ",r[i][j],c[i][j]); printf("\n");}
  memset(f,-63,sizeof(f));
  // rep(x1,1,n) rep(y1,1,n) rep(x2,x1,n) rep(y2,y1,n) printf("%d %d %d %d : %d\n",x1,y1,x2,y2,f[x1][y1][x2][y2]);
  cout << sol(1,1,n,n) << endl;
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值