洛谷 七月月赛

来源:互联网 发布:dede分类目录源码 编辑:程序博客网 时间:2024/05/16 11:33

P3817 小A的糖果

题目描述
小A有N个糖果盒,第i个盒中有a[i]颗糖果。
小A每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中加起来都只有x颗或以下的糖果,至少得吃掉几颗糖。
输入输出格式
输入格式:
第一行输入N和x。
第二行N个整数,为a[i]。
输出格式:
至少要吃掉的糖果数量。
输入输出样例
输入样例#1:
3 3
2 2 2
输出样例#1:
1
输入样例#2:
6 1
1 6 1 2 0 4
输出样例#2:
11
输入样例#3:
5 9
3 1 4 1 5
输出样例#3:
0
说明
样例解释1
吃掉第二盒中的糖果。
样例解释2
第二盒吃掉6颗,第四盒吃掉2颗,第六盒吃掉3颗。
30%的测试数据,2<=N<=20,0<=a[i], x<=100
70%的测试数据,2<=N<=1000,0<=a[i], x<=10^5
100%的测试数据,2<=N<=10^5,0<=a[i], x<=10^9

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define MAXN 100001#define LL long longint N,x,a[MAXN],c[MAXN];LL sum;int main(){    scanf("%d%d",&N,&x);    for(int i=1;i<=N;i++) scanf("%d",&a[i]);    for(int i=1;i<=N;i++){        c[i]=a[i]+a[i-1];        c[i]-=x;    }    for(int i=1;i<=N;i++){        if(c[i]>0){            c[i+1]-=c[i];            sum+=c[i];        }    }    printf("%lld\n",sum);    return 0;}

P3818 小A和uim之大逃离 II

题目背景
话说上回……还是参见 https://www.luogu.org/problem/show?pid=1373 吧
小a和uim再次来到雨林中探险。突然一阵南风吹来,一片乌云从南部天边急涌过来,还伴着一道道闪电,一阵阵雷声。刹那间,狂风大作,乌云布满了天空,紧接着豆大的雨点从天空中打落下来,只见前方出现了一个牛头马面的怪物,低沉着声音说:“呵呵,既然你们来到这,两个都别活了!”。小a和他的小伙伴再次惊呆了!
题目描述
瞬间,地面上出现了一个H行W列的巨幅矩阵,矩阵的每个格子上要么是空地‘.’或者障碍’#’。
他们起点在(1,1),要逃往(H,W)的出口。他们可以一次向上下左右移动一格,这个算一步操作。不过他们还保留着上次冒险时收集的魔液,一口气喝掉后可以瞬移到相对自己位置的(D,R)向量;也就是说,原来的位置是(x,y),然后新的位置是(x+D,y+R),这个也算一步操作,不过他们仅能至多进行一次这种操作(当然可以不喝魔液)。
这个地方是个是非之地。所以他们希望知道最小能有几步操作可以离开这个鬼地方。不过他们可能逃不出这个鬼地方,遇到这种情况,只能等死,别无他法。
输入输出格式
输入格式:
第一行个整数,H W D R,意义在描述已经说明。
接下来H行,每行长度是W,仅有’.’或者’#’的字符串。
输出格式:
请输出一个整数表示最小的逃出操作次数。如果他们逃不出来,就输出-1。
输入输出样例
输入样例#1:
3 6 2 1
…#..
..##..
..#…
输出样例#1:
5
输入样例#2:
3 7 2 1
..#..#.
.##.##.
.#..#..
输出样例#2:
-1
输入样例#3:
6 6 -2 0
.#….
.#.#..
.####.
.#..#.
.##.#.
….#.
输出样例#3:
21
说明
样例解释1
(1,1)→(1,2)→(1,3)→喝(3,4)→(3,5)→(3,6)
样例解释2
因为只有一瓶魔液所以他们没办法逃出来
样例解释3
D和R还可以是0或者负数。
数据范围与约定
40%的测试数据2<=H,W<=5
70%的测试数据2<=H,W<=100
100%的测试数据2<=H,W<=1000,|D|

#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<algorithm>#include<queue>using namespace std;#define LL long long#define MAXN 1005int D,R,n,m;int map[MAXN][MAXN];bool vis[MAXN][MAXN][3];int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};struct Node{ int x,y,step;bool flag; };queue<Node> q;bool Judge(int x,int y){    if(x>0&&x<=n&&y>0&&y<=m) return true;    else return false;}void BFS(){    vis[1][1][0]=1;    Node now;  now.x=1;now.y=1;now.step=0;now.flag=0;    q.push(now);    while(!q.empty()){        Node u=q.front(); q.pop();        for(int i=0;i<4;i++){            int xx=u.x+dx[i],yy=u.y+dy[i];            if(map[xx][yy]==1&&Judge(xx,yy)){                if(vis[xx][yy][u.flag]==0){                    vis[xx][yy][u.flag]=1;                    Node v;                    v.x=xx;v.y=yy;v.step=u.step+1;v.flag=u.flag;                    q.push(v);                    if(v.x==n&&v.y==m){                        printf("%d\n",v.step);                        return ;                    }                }            }        }        if(u.flag==0){            int xx=u.x+D,yy=u.y+R;            if(map[xx][yy]==1&&Judge(xx,yy)){                if(vis[xx][yy][1]==0){                    vis[xx][yy][1]=1;                    Node v;                    v.x=xx;v.y=yy;v.step=u.step+1;v.flag=1;                    if(xx==n&&yy==m){                        printf("%d\n",v.step);                        return ;                    }                    q.push(v);                }            }        }    }    printf("-1");}int main(){    scanf("%d%d%d%d",&n,&m,&D,&R);    char c;    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++){            cin>>c;            if(c=='.') map[i][j]=1;            else if(c=='#') map[i][j]=2;        }    BFS();    return 0;}

P3819 松江1843路

题目描述
涞坊路是一条长L米的道路,道路上的坐标范围从0到L,路上有N座房子,第i座房子建在坐标为x[i]的地方,其中住了r[i]人。
松江1843路公交车要在这条路上建一个公交站,市政府希望让最多的人得到方便,因此希望所有的每一个的居民,从家到车站的距离的总和最短。
公交站应该建在哪里呢?
输入输出格式
输入格式:
第一行输入L、N。
接下来N行,每行两个整数x[i]和r[i]。
输出格式:
一个整数,最小的每个人从家到车站的距离的总和。
输入输出样例
输入样例#1:
100 3
20 3
50 2
70 1
输出样例#1:
110
输入样例#2:
100 2
0 1
100 10
输出样例#2:
100
输入样例#3:
10000000000 5
3282894320 391
4394338332 929
6932893249 181
7823822843 440
9322388365 623
输出样例#3:
5473201404068
说明
样例解释1
当建在坐标40的时候,所有人距离车站的距离总和为 |20?40|×3+|50?40|×2+|70?40|×1=110。
数据范围和约定
对于10%的数据,1≤N≤50,R[i]=1。
对于30%的数据,1≤N≤100,R[i]≤10,1≤L≤1000。
对于70%的数据,1≤N≤1000,R[i]≤100,1≤L≤10^6。
对于全部数据,1≤L≤10^10,1≤N≤10^5,0≤x[i]≤L,1≤r[i]≤1000

//平生头一次写三分#include<iostream>#include<stdio.h>#include<math.h>#include<algorithm>#define LL long long using namespace std;const LL INF=9223372036854775807;const double res=10;struct node{LL x,r;}house[100005];LL lenth,n;LL distan(LL x){    LL sum=0;    for(int i=1;i<=n;i++)        sum+=(abs(x-house[i].x)*house[i].r);    return sum;}int main(){    LL l=INF,r=-INF-1,ans=INF;    scanf("%lld%lld",&lenth,&n);    for(int i=1;i<=n;i++){        scanf("%lld%lld",&house[i].x,&house[i].r);        l=min(l,house[i].x);        r=max(r,house[i].x);    }    l=min(l,(LL)0);    r=max(r,lenth);    LL ll,rl,lm,rm;    while(r-l>res){        lm=l+(r-l)/3,rm=r-(r-l)/3;//三分        ll=distan(lm),rl=distan(rm);        if(ll>=rl) l=lm;        else r=rm;    }      for(LL i=max(l-10,(LL)0);i<=min(r+10,lenth);i++)        ans=min(ans,distan(i));    printf("%lld",ans);    return 0;}

P3820 小D的地下温泉

题目背景
小D最喜欢泡温泉了。小D找某奸商租下了一块行列的地,左上角为,右下角为。小D本以为这块地里全是温泉,结果这块地极不稳定,曾经发生过一些地形变动,所以其中一些地方全是土。
题目描述
一开始他会告诉你当前这块地的情况,但是小D有一些假操作,希望你操作给他看:
由小D指定个位置,他希望知道其中哪个位置下水泡温泉的范围最大。泡温泉的范围定义为指定位置通过向上下左右四个方向能到达的位置的个数。若询问的位置为土,则范围为0。如果如果有多个位置均为最大,输出给出顺序较前的那个。位置编号为。
由小D指定个位置,他会使用膜法按顺序翻转这个地方的地形。即若原位置是土,则该位置变为温泉;若原位置是温泉,则该位置变为土。因为小D不希望活动范围减少得太快,所以他在将温泉变为土时不会将一个区域分割。
输入输出格式
输入格式:
第一行输入两个整数,,为土地大小。
接下来的行每行输入个字符,为’.’(代表温泉)或’*’(代表土)(不包括引号)
第行输入一个整数,,为操作数量。
接下来的行,每行先读入两个整数和,表示操作类型和指定点的数量,在同一行还有个数,分别表示个操作的位置为。
输出格式:
对于每个操作1,输出询问的答案并换行
输入输出样例
输入样例#1:
5 5
.*…
.**
*….


…..
3
1 2 1 1 1 3
2 1 3 1
1 2 1 1 1 3
输出样例#1:
2
1
说明
对于30%的数据,
对于70%的数据,
对于100%的数据,
数据在windows下制作

//二维平面 通过标号 展成 一维坐标//scanf T一个点 #include<iostream>#include<cstring>#include<cstdio>#include<string>#include<algorithm>using namespace std;const int MAXN = 1001000;int n,m,Q,d,a[MAXN],f[MAXN],s[MAXN];int T,w,ans,sum,xx,yy,fa[MAXN],ff;bool flag[MAXN];int Find(int x){    if(x==fa[x]) return x;    else return fa[x]=Find(fa[x]);}inline int read(){    int x=0,f=1;char c=getchar();    while(c>'9'||c<'0'){ if(c=='-')f=-1;c=getchar(); }    while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c-'0');c=getchar(); }    return x*f;}void DFS(int x,int y){    int id=(x-1)*m+y;    if(flag[id]||a[id]==0) return;    flag[id]=1;f[id]=d;s[d]++;    if(x>1) DFS(x-1,y);    if(y>1) DFS(x,y-1);    if(x<n) DFS(x+1,y);    if(y<m) DFS(x,y+1);}void Megre(int x,int y,int x2,int y2){    int d1=(x-1)*m+y,d2=(x2-1)*m+y2;    int f1=Find(f[d1]),f2=Find(f[d2]);    if(a[d1]==0||a[d2]==0||f1==f2) return;    s[f1]+=s[f2];s[f2]=0;fa[f2]=f1;}int main(){    //scanf("%d%d",&n,&m);    n=read();m=read();    char ch;    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++){            ch=getchar();            while(ch!='.'&&ch!='*') ch=getchar();            if(ch=='.') a[(i-1)*m+j]=1;        }    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++){            if(a[(i-1)*m+j]==1&&!flag[(i-1)*m+j]){                d++;                DFS(i,j);            }        }    for(int i=1;i<=d;i++) fa[i]=i;//  scanf("%d",&Q);    Q=read();    while(Q--){        T=read();w=read();        //scanf("%d%d",&T,&w);        if(T==1){            ans=1;sum=0;            for(int i=1;i<=w;i++){                xx=read();yy=read();                //scanf("%d%d",&xx,&yy);                ff=Find(f[(xx-1)*m+yy]);                if(a[(xx-1)*m+yy]==0) continue;                if(s[ff]>sum) sum=s[ff],ans=i;            }            printf("%d\n",ans);        }        else{//翻转            while(w--){                xx=read();yy=read();//              scanf("%d%d",&xx,&yy);                if(a[(xx-1)*m+yy]==1){                    a[(xx-1)*m+yy]=0;                    ff=Find(f[(xx-1)*m+yy]);                    s[ff]--;                    f[(xx-1)*m+yy]=0;                } else{                    a[(xx-1)*m+yy]=1;d++;                    f[(xx-1)*m+yy]=d;fa[d]=d;                    s[d]++;                    if(xx>1) Megre(xx,yy,xx-1,yy);                    if(yy>1) Megre(xx,yy,xx,yy-1);                    if(xx<n) Megre(xx,yy,xx+1,yy);                    if(yy<m) Megre(xx,yy,xx,yy+1);                }            }        }    }    return 0;}/*题解思路:先用dfs/bfs搜连通块,并且标号,然后修改,分两种情况,土变成温泉,要和周围的连通块合并温泉变成土,面积直接减然后查询,直接一个一个扫就行。*/
原创粉丝点击