2019山东省赛重现补题总结

题外话

赛后做了一下队友做的H和没做出来的L
感觉其实还挺简单, 就是没往那边去想,亦或者说,对这个算法掌握的不熟练。

H 题目链接

题意

给你几个线段, 然后你可以在每个线段上找一个点(这个点必须是在y轴方向上, 没有别的点和它平行,就是一竖行上只能有一个点),然后问你有这个点的线段(这个线段至少有一个点,多个也没问题)有多少

思路

一看给的是一条线段的左右端点, 肯定考虑对左端点排序,再对右端点排序

  • 这个题,因为可能会给你在x点相同,y点不同的几条线段(例子: 1 2 1 2 1 2(他y根据题目上说是i,就是从i =1 开始) 就是 (1,1)(2,1) (1 , 2) (2 , 2) (1,3 )(2, 3)),所以我们需要判断当前点移动的位置上,y轴有没有被占用,
    • 没有就使用
    • 有的话,就移动当前点(只要当前点x 还小于当前的y就行)++ , 发现超过这条线段的右端点, 那么就跳到另外一条线段上
  • 通过上面的分析, 我们只需要用一个优先队列并对 < 进行重载就行了

代码

#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define pn printf("
");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d
",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
#define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)

using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const LL Max = 9.1e10;
const int N =3.1e5;
const int maxn = 200010;

void clear(unsigned char *pta, int size )
{//结构体初始化
    while(size>0)
    {
        *pta++ = 0;
        size --;
    }
}

LL   n, k, m ;
LL ar[N],br[N];
LL i,j,g;
LL MOD = 998244353 ;
struct node {
    int l ,r ;
    bool operator < (const node & x)const {
        if(l==x.l)return r > x.r;
        return l>x.l;
    }

};

priority_queue<node > q;

void answer(){
    cin >>n ;

    for(int i=1 ;i<=n;i++){
        node  no;
        cin >>no.l>>no.r;
        q.push(no);
    }
    LL cnt =0  , h = 0;
    while(!q.empty()){
        node New = q.top();
        q.pop();
        if(New.l>h){
            cnt ++ ;
            h = New.l;
        }
        else if(New.l < New.r){
            New.l++ ;
            q.push(New);
        }
    }
    cout<<cnt<<endl;

   return ;
 }


int main()
{
//    ios::sync_with_stdio(0);
//    cin.tie(0), cout.tie(0);
//       pre();
    LL t;sld(t);
    while(t--)
        answer();


    return 0;

}

L 题目链接

题意

给你几个点,然后告诉你这些点左边严格大于右边,问你 有几个点可以成为中间的点

思路

因为条件是大于的关系, 所以可以把这个看成一个有向图(左边的点指向右边的点)

  • 这样我们只需要考虑什么情况下,这个有向图能够有点在中间呢?
    • 首先,我们根据离散的知识(数据结构也行)知道,有自环的有向图肯定是不能成立的(要么这个图不能联通, 要么这个图成为环)
    • 然后, 我们此时只需要考虑什么能求闭包问题的算法 ,发现floyed算法, 但是因为它的复杂度太高,再看看数据,发现数据范围还行,那就直接上手!
  • 在找到算法和思路后, 只需要最后判断一下, 每个点的出度和入度是否是大于等于(等于是因为题面说 n 一定是个奇数)(n+1)/2即可

代码

#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define pn printf("
");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d
",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
#define dbg(x...) do { cout << "33[32;1m" << #x << " -> "; err(x); } while (0)

using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const LL Max = 9.1e10;
const int N =3.1e5;
const int maxn = 200010;

void clear(unsigned char *pta, int size )
{//结构体初始化
    while(size>0)
    {
        *pta++ = 0;
        size --;
    }
}

LL   n, k, m ;
LL ar[N],br[N];
LL i,j,g;
LL MOD = 998244353 ;

LL floyed[110][110];
LL in[maxn],out[maxn];



LL fac[N],inv_fac[N];
//快速幂
LL qpow(LL x, LL y ){
    x%=MOD;
    long long res=1%MOD;
    while(y){
        if(y&1)res=res*x%MOD;
        y>>=1;
        x=x*x%MOD;
    }
    return res;

}

void pre(){
    fac[0] =1 ;
    for(int i=1;i<N;i++){
        fac[i] =fac[i-1] * i %MOD;
    }
    inv_fac[N - 1 ] = qpow(fac[N - 1] , MOD-2 ) ;

    for(int i =N-2 ;i>=0 ;i--){
        inv_fac[i] = inv_fac[i+1] * (i+1) %MOD;
    }

}

LL C (LL a ,LL b){
    if(a<0 || b> a )//因为是C(a,b) 所以b《= a
    {
        return 0;
    }

    return fac[a] * inv_fac[b] % MOD *inv_fac[a-b]%MOD;//a 的阶乘 / ( b的阶乘 * (a-b的阶乘))

}

void answer(){
    sld(n); sld(m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            floyed[i][j] =0 ;
        }
    }
    for(int i=1;i<=m;i++){
        int x, y ;s(x);s(y);
        floyed[x][y] =1 ;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            for(int g=1;g<=n;g++){
                floyed[j][g] |= floyed[j][i]&floyed[i][g];
            }
        }
    }
    cl(in),cl(out);int flag = 0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(floyed[i][j]){
                if(i == j){
                    flag = 1 ;
                    break;
                }
                in[j]++;
                out[i] ++;
            }

        }
        if(flag)break;
    }
    if(flag){
        for(int i=1;i<=n;i++)p(0);pn;
        return ;
    }

    for(int i=1;i<=n;i++){
        if(in[i]>=((n+1)/2)||out[i]>=((n+1)/2)){
            p(0);
        }
        else {
            p(1);
        }

    }pn;
   return ;
 }


int main()
{
//    ios::sync_with_stdio(0);
//    cin.tie(0), cout.tie(0);
//       pre();
    LL t;sld(t);
    while(t--)
        answer();


    return 0;

}

原文地址:https://www.cnblogs.com/gaohaoy/p/13752802.html