11.08练习赛

11.08练习赛

T1 吃糖

这道题没有什么好说的,从100枚举到2,用\(N^2\)的搜索暴力\(Check\)即可。

然而我打爆了

最后发现是在dfs2里条件判断错误。

我真是个憨憨

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
char *p1,*p2,buf[1<<20];
//#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++)))
#define GC getchar()
#define ri register int
inline int in()
{
    int w=0,x=0;
    char ch=0;
    while(!isdigit(ch)){
        w|=ch=='-';
        ch=GC;
    }
    while(isdigit(ch)){
        x=(x<<3)+(x<<1)+(ch^48);
        ch=GC;
    }
    return w? -x:x;
}
int r,c;
int a[110][110];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int _max;
int cut=0;
struct point{
    int x,y;
};
queue<point>q;
bool vis[110][110];
bool vis1[110][110];
void dfs(int x,int y,int k)
{
    vis[x][y]=1;
    cut+=1;
    int i;
    for(i=0;i<4;i++){
        int tx=x+dx[i],ty=y+dy[i];
        if(vis[tx][ty])continue;
        if(tx==0||tx==r+1||ty==0||ty==c+1)continue;
        if(a[tx][ty]<k)continue;
        dfs(tx,ty,k);
    }
    return;
}
int dfs1(int x,int y)
{
    vis1[x][y]=1;
    int i;
    int k=1;
    for(i=0;i<4;i++){
        int tx=x+dx[i],ty=y+dy[i];
        if(vis[tx][ty])continue;
        if(vis1[tx][ty])continue;
        if(tx==0||tx==r+1||ty==0||ty==c+1)continue;
        k+=dfs1(tx,ty);
    }
    return k;
}
bool check(int x)
{
    memset(vis,0,sizeof(vis));
    memset(vis1,0,sizeof(vis1));
    int i,j;
    cut=0;
    for(i=1;i<=c;i++){
        if(a[1][i]>=x)q.push((point){1,i});
        if(a[r][i]>=x)q.push((point){r,i});
    }
    for(i=1;i<=r;i++){
        if(a[i][1]>=x)q.push((point){i,1});
        if(a[i][c]>=x)q.push((point){i,c});
    }
    while(q.size()){
        int A=q.front().x,B=q.front().y;
        q.pop();
        if(vis[A][B])continue;
        dfs(A,B,x);
    }
    for(i=1;i<=r;i++)
    {
        for(j=1;j<=c;j++)
        {
            if(!vis[i][j]){
                int k=dfs1(i,j);
                if(k==r*c-cut){
                    return 0;
                }
                else return 1;
            }
        }
    }
    return 0;
}
bool inf[110];
int main()
{
//  freopen("candies.in","r",stdin);
//  freopen("candies.out","w",stdout);
    r=in();c=in();
    ri i,j;
    for(i=1;i<=r;i++)
    {
        for(j=1;j<=c;j++)
        {
            a[i][j]=in();
            inf[a[i][j]]=1;
            _max=max(_max,a[i][j]);
        }
    }
    for(i=_max;i>=2;i--)
    {
        if(check(i)){
            printf("%d\n",i);
            return 0;
        }
    }
    printf("-1\n"); 
    return 0;
}

T2 卡片

题面是真的长,而且大部分都没用

稍微描述一下题面:

其实就是一个三关键字排序,问最多能选出多少个连续的数集。

听liudl带佬说是三维偏序,于是我打了个二位数点(逃

首先膜一下Qhr带佬,他居然是(本人所知)全小机房唯一一个想出来可以用图论来搞这道题人。而这也是本题的正解(之一)。能拿20那种

(具体做法是把所有\(p_i<p_j\)的点连起来,然后跑最长路)

正解是用一个叫做CDQ分治的东西把三维转换成二维。然而我并不会

还有一个正解就是把20分做法和80分做法整合起来,就能A掉了。

注:在这种小规模的最短/长路中最好用SPFA,又短又好写而且小数据绝对卡不掉。(关于SPFA:他活了)

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
char *p1,*p2,buf[1<<20];
//#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++)))
#define GC getchar()
inline int in() {
    int x=0,w=0;
    char ch=0;
    while(!isdigit(ch)) {
        w|=ch=='-';
        ch=GC;
    }
    while(isdigit(ch)) {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=GC;
    }
    return w? -x:x;
}
inline int lowbit(int x) {
    return x&(-x);
}
const int maxn= 1e6 + 5;
struct node {
    int x,y,z;
} g[maxn];
int _max;
int n;
namespace s1 {
    bool cmp(node a,node b) {
        if(a.x!=b.x)return a.x<b.x;
        else return a.y<b.y;
    }
    int sum[1000010];
    void ins(int x,int k) {

        for(; x<=maxn; x+=lowbit(x)) {
            sum[x]=max(sum[x],k);
            if(x==0)break;
        }
        return;
    }
    int gs(int x) {
        int res=0;
        for(;;x-=lowbit(x)) {
            res=max(res,sum[x]);
            if(x==0)break;
        }
        return res;
    }
    void s1() {
        sort(g+1,g+n+1,cmp);
        int ans=0;
        for(int i=1; i<=n; ++i) {
            int v=g[i].y;
            ins(v,gs(v)+1);
            ans=max(ans,gs(v));
        }
        printf("%d\n",ans);
        return;
    }
}
namespace s2 {
    struct edge {
        int to,next;
    } e[maxn*2];
    int head[maxn],cnt;
    void add(int from,int to) {
        e[++cnt].next=head[from];
        e[cnt].to=to;
        head[from]=cnt;
    }
    int ans=0;
    bool inq[maxn];
    int dis[maxn];
    queue<int>q;
    void spfa(int x)
    {
        for(int i=1;i<=n;i++)dis[i]=inq[i]=0;
        q.push(x);
        inq[x]=1;
        while(q.size()){
            int u=q.front();
            q.pop();
            inq[u]=0;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(dis[u]+1>dis[v]){
                    dis[v]=dis[u]+1;
                    if(!inq[v]){
                        q.push(v);
                        inq[v]=1;
                    }
                }
            }
        }
    }
    void s2() {
        int i,j;
        for(i=1; i<=n; i++) {
            for(j=1; j<=n; j++) {
                if(i==j)continue;
                if(g[i].x<=g[j].x&&g[i].y<=g[j].y&&g[i].z<=g[j].z){
                    add(i,j);
                }
            }
        }
        for(i=1; i<=n; i++) {
            spfa(i);
            for(j=1;j<=n;j++)
            {
                ans=max(ans,dis[j]+1);
            }
        }
        printf("%d\n",ans);
        return;
    }
}
int main() {
    bool if0=1;
    n=in();
    for(int i=1; i<=n; ++i) {
        g[i].x=in();
        g[i].y=in();
        g[i].z=in();
        if(g[i].z!=0)if0=0;
        _max=max(g[i].y,_max);
    }
    if(if0) {
        s1::s1();
        return 0;
    } else {
        s2::s2();
        return 0;
    }
}

这次想装一下B所以用了用namespace,好孩子不要学

猜你喜欢

转载自www.cnblogs.com/cooper233/p/11828758.html
今日推荐