-TEST 16 for NOIP 让scar_lyw都绝望的T3(120-300)

头更更大

这个10月完就要去搞NOIP了。。。

10月30天也就3次测试。。。为保佑进省一我还是每次测试玩都写个总结。。


emm…最后一题的暴力打炸了。。。
本来这个成绩还能够勉勉强强接受:
T1苟住,T2暴力Floyed嘲讽,T3暴力爆炸 = 120
然后。。
T3把我,scar_lyw,tshoigyr调了1个多小时。。。。。。。。。。。。。
emmm……….

下面面详细解答:

T1(100/100):机器清理工

problem

题意:。。。。。。矩阵前缀和模板
样例

  • 输入
    1
    2
    4 4 10
    6 6 20
  • 输出
    1 30

solution

前缀和模板不解释。

T2(0/100):朋友

problem

题意:emm。。。
给你一个矩阵,每个点有一个权值,从这个点你可以转移到其他任意一个与这个点的曼哈顿距离不大于这个点的权值的点。每次转移的代价为这个点的另一个权值。(题目中是一个人可以这样通过弹射器射到另一个城市)
给你三个点(只有一组数据),问你从另外两个点到达其中一个点的最小代价是多少。
(就是一个魔改了的最短路)
样例

  • 输入
    4 4
    0 0 0 0
    1 2 2 0
    0 2 2 1
    0 0 0 0
    5 5 5 5
    5 5 5 5
    5 5 5 5
    5 5 5 5
    2 1
    3 4
    2 2

  • 输出
    Z
    15

solution

20%的暴力有用Dijkstra的。。。有用SPFA的。。。
然而只有我用的是六阶Floyed!!!啊哈哈哈哈哈哈哈哈哈
这里写图片描述

咳咳

下面正解

100%正解很不好想但是真的很巧妙:
首先让我们新增一个云端的概念。
在之前我们绝大多数的人可能认为如果真的拿一群人去模拟的话。。
真实情况应该是这样的。。。
这里写图片描述
然而题解认为可以这样搞:
不一定是像大炮那样射来射去
可以是把人射到高空然后让他缓缓降落(曼哈顿距离):
这里写图片描述
(emm。。这里好像画的不很好。。)
于是!
我们‘建立’一个图:g[x][y][h]:
x:横坐标,y:纵坐标,h:高度
当人在云端节点上时,他必须向低一层的云端节点上降落。
这里写图片描述
于是每个云端节点将向下连5条边。
然而地面的发射器只用把人射到指定高度就行了。。
所以地面节点只用向上连一条边
上面的人只要要么一直往一个方向飞要么盘旋下来就行了。

于是只要建N*M*S个点就行了,每个云端节点连接5条边,每个地面节点连一条边。
然后本来一直困扰我们的因为需要建的边太多导致MLE的问题就解决了!开不开心!!

然而!
这道题实际上不用建边!!
用好Dijkstra的原理直接在矩阵开干!!!

具体实现见后面代码。
(bzoj2143)

T3(30/100):纸带

problem

题意
给你一个数组(1~1e9),对其进行N次操作,第 i 次操作把区间Li~Ri的值都赋为 i (如果之前有数就覆盖它),问最后剩余多少种数。
样例

  • 输入 
    4
    0 5
    3 8
    5 6
    4 7

  • 输出
    3

solution

emmm。。感觉以前做过这道题但是想不起来了。
考试时模拟暴力枚举GG了。

然后最神奇的是我改了半天最后总是莫名其妙最后30%的数据总是RE,然而我的数组没有爆,也没有陷入死循环。
我搞了半个小时。。然后没搞出来。
然后去问 大佬#1 tshoigyr,他觉得可能是我数组开小了
然后去问 大佬#2 scar_lyw,她立刻接受了。。。。。。

emm。。。
然后调了半个小时没找到问题。。有点不能接受
然后把tshoigyr找来一起调。。。发现程序运行得好好的莫名崩溃了。。感到绝望了。。
然后三个人继续一点点找问题。。发现在递归到这个数
1172172
的时候,程序就强制崩溃了。。。。。。

。。。scar_lyw差点自己崩溃的哭出来。。。

然后请了一个专门研究编译器的大佬,说可能是爆栈了:

int fa[kkk<<2],jud[kkk<<2];
int getfa(int x){return((fa[x]==x)?(x):(fa[x]=getfa(fa[x])));}

结果还真是。。。。。

更神奇的是加个inline就完事了。。。

int fa[kkk<<2],jud[kkk<<2];
inline int getfa(int x){return((fa[x]==x)?(x):(fa[x]=getfa(fa[x])));}

事实上加inline的时候我也很迷啊不是说好了递归很深的函数不能加inline吗然而这道题是要么你加inline要么你手动开栈(然而NOIP不让用这个)否则最后六个点就不过就是RE不服你来打我啊啊哈哈哈哈哈哈哈哈哈

感想

emm。。。。。
以后所有的子函数都加上inline好了。。。
然后这几天别刷题了。。把做过的题好好重新做一遍。

代码:

T1:

my/std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

#define U_MAX 200
inline char *stdin_get_str(char *str)
{
    fgets(str,U_MAX,stdin);
    if(str[strlen(str)-1] == '\n')
        str[strlen(str)-1] = '\0';
    return str;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

int n,d,x,y,z;
int cnt=1,ans=0;
int f[2000][2000];

int main()
{
    d=read();   n=read();
    while(n--){x=read();y=read();f[x+1][y+1]=read();}

    for(int i=1;i<=1025;i++)
        for(int j=1;j<=1025;j++)
            f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];

    for(int i=2*d+1;i<=1025;i++)
        for(int j=2*d+1;j<=1025;j++)
        {
            int jud = ans;
            ans=max(ans,f[i][j]-f[i-2*d-1][j]-f[i][j-2*d-1]+f[i-2*d-1][j-2*d-1]);
            if(jud==f[i][j]-f[i-2*d-1][j]-f[i][j-2*d-1]+f[i-2*d-1][j-2*d-1])cnt++;
            else if(ans>jud)cnt=1;
        }

    cout << cnt << " " << ans << endl;      
    return 0;       
}

T2

my.cpp

稳稳的20%六阶Floyed嘲讽式暴力

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

#define U_MAX 200
inline char *stdin_get_str(char *str)
{
    fgets(str,U_MAX,stdin);
    if(str[strlen(str)-1] == '\n')
        str[strlen(str)-1] = '\0';
    return str;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=1000005;

int n,m,ans;
int s1,s2,s3;
int a[25][25];
int b[25][25];
int f[25][25][25][25];
int xx[4],yy[4];

int main()
{
    freopen("friend.in","r",stdin);
    freopen("friend.out","w",stdout);   
    for(int k1=0;k1<=24;k1++)
        for(int k2=0;k2<=24;k2++)
            for(int i1=0;i1<=24;i1++)
                for(int i2=0;i2<=24;i2++)
                    f[k1][k2][i1][i2]=99999999; 

    n=read();   m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            a[i][j]=read();

    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            b[i][j]=read();
            for(int x=0;x<=a[i][j];x++)
                for(int y=0;y<=a[i][j]-x;y++)   
                {
                    f[i][j][max(1,i-y)][max(1,j-x)]=(b[i][j]);                      
                    f[i][j][min(n,i+y)][min(m,j+x)]=(b[i][j]);                      
                    f[i][j][max(1,i-y)][min(m,j+x)]=(b[i][j]);                      
                    f[i][j][min(n,i+y)][max(1,j-x)]=(b[i][j]);                                                          
                }
        }

    for(int k1=1;k1<=n;k1++)
        for(int k2=1;k2<=m;k2++)
            for(int i1=1;i1<=n;i1++)
                for(int i2=1;i2<=m;i2++)
                    for(int j1=1;j1<=n;j1++)
                        for(int j2=1;j2<=m;j2++)
                            f[i1][i2][j1][j2]=min(f[i1][i2][j1][j2],f[i1][i2][k1][k2]+f[k1][k2][j1][j2]);

    for(int i=1;i<=3;i++)xx[i]=read(),yy[i]=read(); 

    s1=f[xx[2]][yy[2]][xx[1]][yy[1]]+f[xx[3]][yy[3]][xx[1]][yy[1]]; 
    s2=f[xx[1]][yy[1]][xx[2]][yy[2]]+f[xx[3]][yy[3]][xx[2]][yy[2]];
    s3=f[xx[1]][yy[1]][xx[3]][yy[3]]+f[xx[2]][yy[2]][xx[3]][yy[3]];

    ans = min(s1,min(s2,s3));

    if(ans==s1)cout<<"X"<<endl;     
    else if(ans==s2)cout<<"Y"<<endl;    
    else if(ans==s3)cout<<"Z"<<endl;    

    cout << ans << endl; 
    return 0;
}

std.cpp

题解来自hzwer。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define ll long long
#define inf 1000000000
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char ans;int mn=inf;
int xx[5]={0,0,1,-1,0},yy[5]={1,-1,0,0,0};
int a1,a2,b1,b2,c1,c2;
int n,m,mx;
int x1,y1,x2,y2,x3,y3;
int a[155][155],b[155][155];
int d[155][155][305];
bool vis[155][155][305];
struct data{int w,x,y,s;};
bool operator>(data a,data b)
{
    return a.w>b.w;
}
void dij(int x,int y)
{
    priority_queue<data,vector<data>,greater<data> > q;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<=mx;k++)
            {
                vis[i][j][k]=0;
                d[i][j][k]=inf;
            }
    vis[x][y][0]=1;
    d[x][y][a[x][y]]=b[x][y];
    q.push((data){b[x][y],x,y,a[x][y]});
    while(!q.empty()&&(!vis[x1][y1][0]||!vis[x2][y2][0]||!vis[x3][y3][0]))
    {
        int x=q.top().x,y=q.top().y,s=q.top().s;q.pop();
        if(vis[x][y][s])continue;vis[x][y][s]=1;
        if(s>0)
        {
            for(int k=0;k<5;k++)
            {
                int nowx=x+xx[k],nowy=y+yy[k];
                if(nowx<1||nowy<1||nowx>n||nowy>m||vis[nowx][nowy][s-1])continue;
                if(d[x][y][s]<d[nowx][nowy][s-1])
                {
                    d[nowx][nowy][s-1]=d[x][y][s];
                    q.push((data){d[nowx][nowy][s-1],nowx,nowy,s-1});
                }
            }
        }
        else
        {
            int t=a[x][y];
            if(d[x][y][t]>d[x][y][0]+b[x][y])
            {
                d[x][y][t]=d[x][y][0]+b[x][y];
                q.push((data){d[x][y][t],x,y,t});
            }
        }
    }
    while(!q.empty())q.pop();
}
int main()
{   
    n=read();m=read();mx=n+m-2;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            a[i][j]=read();
            a[i][j]=min(a[i][j],max(mx-i-j,i+j-2));
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            b[i][j]=read();
    x1=read();y1=read();x2=read();y2=read();x3=read();y3=read();
    dij(x1,y1);a1=d[x2][y2][0];a2=d[x3][y3][0];
    dij(x2,y2);b1=d[x1][y1][0];b2=d[x3][y3][0];
    dij(x3,y3);c1=d[x1][y1][0];c2=d[x2][y2][0];
    if(b1+c1<mn)mn=b1+c1,ans='X'; 
    if(a1+c2<mn)mn=a1+c2,ans='Y';
    if(a2+b2<mn)mn=a2+b2,ans='Z';
    if(mn==inf)puts("NO");
    else
    {
        printf("%c\n",ans);
        printf("%d\n",mn);
    }
    return 0;
}

T3

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

const int kkk = 1000000 + 10;
int n,cnt,top;
int l[kkk],r[kkk];

int fa[kkk<<2],jud[kkk<<2];
inline int getfa(int x){return((fa[x]==x)?(x):(fa[x]=getfa(fa[x])));}

struct data {
    int num,type,id;
    inline bool operator < (const data &b) const {return num < b.num;}
}a[kkk<<1];

inline void read_in() 
{
    n=read();
    for(int i=1;i<=n;++i) 
    {
        a[++cnt].num=read(),a[cnt].id=i,a[cnt].type=0,a[cnt].num++;
        a[++cnt].num=read(),a[cnt].id=i,a[cnt].type=1;
    }
}

inline void solve() 
{
    sort(a+1,a+cnt+1);int i=1;
    while(i<=cnt) 
    {
        int j=i;
        while(a[i].num==a[i+1].num) 
        {
            if(i==cnt)break;
            ++i;
        }
        if(j!=1&&a[j-1].num+1<a[i].num)top+=2;
        else ++top;
        for(int k=j;k<=i;++k)(a[k].type)?(r[a[k].id]=top):(l[a[k].id]=top);
        ++i;
    }
}

inline bool cover(int l, int r) 
{
    register int i = getfa(l);
    if(i>r) return false;
    for(;i<=r;i=getfa(i))fa[i]=getfa(i+1);
    return true;
}

int ans=0;
inline void get_ans()
{
    for(int i=1;i<=top+10;i++)fa[i]=i;
    for(int i=cnt/2;i>=1;i--)
        if(cover(l[i],r[i]))ans++;
    cout << ans << endl;
}

int main()
{
    read_in();
    solve();
    get_ans();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值