10.15 loitest 未完

来源:互联网 发布:windows phone升级 编辑:程序博客网 时间:2024/06/05 08:57

  • 出题人
  • Problem 1 DQS 捡石子
    • 题目来源
    • 题目描述
    • 题解
    • 代码
  • Problem 2 DQS 讲笑话
    • 题目来源
    • 题目描述
    • 题解
    • 代码
  • Problem 3 DQS 找宝藏
    • 题目来源
    • 题目描述

出题人

swc学长 http://blog.csdn.net/wwwasdirine

Problem 1 DQS 捡石子

题目来源

https://vjudge.net/problem/HDU-5583

题目描述

今年开始上学的 DQS 非常喜欢石子, 她总是会收集很多不同类型的石子来卖钱, 这个世界的石子只有两种——蓝色和白色(用01 表示) 并且都是连在一起的, 不能移动, 因此 DQS 只好使用她的神力来解除石子不能移动的封印, 但是由于某些原因 DQS 希
望让自己消耗更多的神力, 因此她许愿黑暗之神让她可以转换连在一起的石子中的一颗。 消耗的神力计算方法为这一串石子中相邻相同的石子个数的平方和。 DQS 想知道, 如何改变其中一个石子的种类, 使得整个石子串的消耗最大(含多组数据)

输入描述
一个数 T
接下来 T 行, 每行一个长度为 N 的 01 串

输出描述
一个数 p 表示 DQS 消耗的神力

样例输入
2
000011
0101

样例输出
26
10

数据范围及提示
1<=T<=50
60%:1<=N<=1000
100%:1<=N<=100000

题解

通过正序和逆序两遍循环,我们可以处理出以任意元素为起点和终点的相同序列的长度
计算出一个初始的答案
然后枚举每一个元素作为改变的位置(显然改变序列中部一定不会最优,可以跳过)
大致分为下列三种情况
0011
改变第二位的0 某个序列的末尾元素
第三位的1 某个序列的初始元素
010
改变1 两个序列之间的唯一元素

将ans进行加减,取max

代码

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int N=100000+50;long long ed[N],be[N],len;char a[N];long long ans,maxx,tmp;long long t;long long  pf(long long  x){    long long ha=x*x;    return ha;}void done(){    for(int i=1;i<=len;i++){        if(a[i]==a[i-1]){            ed[i]=ed[i-1]+1;        }        else {            ans+=ed[i-1]*ed[i-1];            ed[i]=1;            }    }    ans+=pf(ed[len]);    for(int i=len;i>=1;i--){        if(a[i]==a[i+1]){            be[i]=be[i+1]+1;        }        else be[i]=1;    }}void init(){    maxx=-1;    ans=0;    memset(ed,0,sizeof(ed));    memset(be,0,sizeof(be));    return ;}void done1(int i){    tmp=ans;    tmp-=pf(ed[i-1]);    tmp+=pf(ed[i-1]+1);    tmp-=pf(be[i]);    tmp+=pf(be[i]-1);    maxx=max(tmp,maxx);}void done2(int i){    tmp=ans;    tmp-=pf(ed[i]);    tmp+=pf(ed[i]-1);    tmp-=pf(be[i+1]);    tmp+=pf(be[i+1]+1);    maxx=max(tmp,maxx);}void done3(int i){    tmp=ans;    tmp-=pf(ed[i-1]);    tmp-=pf(be[i+1]);    tmp-=1;    tmp+=pf(ed[i-1]+be[i+1]+1);    maxx=max(tmp,maxx);}int main(){    scanf("%lld",&t);    for(int ha=1;ha<=t;ha++){        init();        cin>>a+1;        len=strlen(a+1);        done();        maxx=ans;        for(int i=2;i<len;i++){            if(a[i-1]==a[i]&&a[i]==a[i+1]) continue;            if(a[i]!=a[i-1]&&a[i]==a[i+1]){                done1(i);            }            if(a[i]==a[i-1]&&a[i]!=a[i+1]){                done2(i);            }            if(a[i]!=a[i-1]&&a[i]!=a[i+1]){                done3(i);            }        }        if(a[1]!=a[2]){            tmp=ans;            tmp-=1;            tmp-=pf(be[2]);            tmp+=pf(be[2]+1);            maxx=max(tmp,maxx);        }         if(a[len]!=a[len-1]){            tmp=ans;            tmp-=1;            tmp-=pf(ed[len-1]);            tmp+=pf(ed[len-1]+1);            maxx=max(tmp,maxx);        }        printf("Case #%d: %lld\n",ha,maxx);    }}

Problem 2 DQS 讲笑话

题目来源

https://vjudge.net/problem/Gym-101350F

题目描述

在一个平行世界中, 生活着无数只 DQS。 这里的 DQS 不喜欢捡石子, 她们只喜欢讲笑话。 一天, 有 n 只DQS 坐在一起讲笑话, 有 m 次讲笑话的机会。由于这个世界的 DQS太喜欢讲笑话了, 所以很多笑话她们都是讲过的。 因此这一次DQS 们讲笑话时也是从现有的笑话库中找笑话出来讲, 每次 DQS讲第 li 种笑话, 影响的范围是向左向右 ki 只 DQS, 同时自己也会受到影响。 一只 DQS 如果听到了一个没听过的笑话会笑趴下,但她如果听到了一个听过的笑话会坐起来。 一开始所有的 DQS 都是坐着的。
问最后有多少 DQS 是坐着的呢

输入描述
第一行两个数 n,m
接下来 m 行 每行三个数 xi(表示第几只 DQS 讲笑话) ,li(第几种笑话) ,ki(影响 2ki+1 只 DQS)

输出描述
一个数 p, 表示有 p 只 DQS 最后是坐着的

样例输入
10 7
3 11 0
3 11 2
5 12 1
8 13 2
7 11 2
10 12 1
9 12 0

样例输出
3

数据范围及提示
对于 30% n<=100, m<=100
对于 60% n<=10000,m<=10000
对于 100% n<=100000,m<=100000, 1<=li<=100000
1<=x<=n,0<=k<=n

题解:

首先,可以明确的是,某点最终的状态,取决于它听到的最后一个笑话
若听到的最后一个笑话是第一次 ans不更新
不是第一次 ans更新
从未听到过笑话 ans更新

还有别的做法

一:stl法

http://blog.csdn.net/fanesemyk/article/details/76557632
借鉴了这位大佬很多

开一个vector的二维数组,读入每一条线段,在始点push进去笑话的编号,在末点的下一位push进去笑话的编号的相反数(负值)
运用set元素唯一且能迅速查询删除指定大小的元素的功能
我们从第一个点开始循环
如果vector中有一个正值,说明有一个笑话从这个点开始,丢入set,如果有一个负值,说明有一个笑话到这里结束,从set中删除,更新num数组(表示每个笑话出现的次数)
某点i循环完毕后,
若set为空,说明某点根本就没有笑话,ans++
若set不为空,那么set的末尾元素就是该点听到的最后一个笑话,如果对应的num>1,说明笑话出现了不止一次 ans++
由于是从一开始枚举,不存在遗漏当前节点的笑话的情况

将笑话按照顺序进行编号,对应起来,避免了两个部分重叠的相同笑话的线段在进行set操作时的错误情况,同时又维护了每个笑话出现的次数

这里写图片描述
如图如果不进行编号,而是按照笑话的种类,在执行到黄点时,当前笑话就会被弹出set,从黄点到绿点这一部分的笑话就会失去

代码:

stl代码#include<iostream>#include<cstdio>#include<algorithm>#include<set>#include<vector>#include<cstring>using namespace std;int n,m,x,l,k;const int N=100000+500;int num[N],type[N],ans;vector<int> e[N];set<int> s;void init(){    for(int i=0;i<=n+3;i++) e[i].clear();    s.clear();    ans=0;    memset(num,0,sizeof(num));    memset(type,0,sizeof(type));}int main(){    int T;    scanf("%d",&T);    while(T--){        init();        scanf("%d%d",&n,&m);        for(int i=1;i<=m;i++){            scanf("%d%d%d",&x,&l,&k);            type[i]=l;            int z=max(1,x-k),y=min(n,x+k);            e[z].push_back(i);            e[y+1].push_back(-i);        }        for(int i=1;i<=n;i++){            int sz=e[i].size();            for(int j=0;j<sz;j++){                int t=e[i][j];                if(t>0){                    s.insert(t);                    num[type[t]]++;                }                else{                    s.erase(-t);                    num[type[-t]]--;                }            }            if(s.empty()) ans++;            else{                int p=*(--s.end());                if(num[type[p]]>1) ans++;            }        }        printf("%d\n",ans);     }    return 0;}

Problem 3 DQS 找宝藏

题目来源

http://www.lydsy.com/JudgeOnline/problem.php?id=1924

题目描述

另一个平行世界中的 DQS 既不喜欢捡石子也不喜欢讲笑话, 她们喜欢—
—寻宝!
于是这一天 DQS 来到一个沉睡着古神的神殿中来探宝整座宫殿呈矩阵状,由 R×C 间矩形宫室组成,其中有 N 间宫室里埋藏着宝藏,称作藏宝宫室。 宫殿里外、 相邻宫室间都由坚硬的实体墙阻隔,由一间宫室到达另一间只能通过古神独创的移动方式——传送门。 古神为这N 间藏宝宫室每间都架设了一扇传送门,没有宝藏的宫室不设传送门,所有的宫室传送门分为三种:
1、 “横天门” :由该门可以传送到同行的任一宫室;
2、 “纵寰门” :由该门可以传送到同列的任一宫室;
3、 “自由门” :由该门可以传送到以该门所在宫室为中心周围 8 格中任一宫室(如果目标宫室存在的话)。
深谋远虑的 DQS 当然事先就搞到了古神当年的宫殿招标册,书册上详细记录了每扇传送门所属宫室及类型。 而且,虽然宫殿内外相隔,但他自行准备了一种便携式传送门,可将自己传送到殿内任意一间宫室开始寻宝,并在任意一间宫室结束后传送出宫。 整座宫殿只许进出一次,且便携门无法进行宫室之间的传送。 不过好在宫室内传送门的使用没有次数限制,每间宫室也可以多次出入。
现在 DQS 已经打开了便携门,即将选择一间宫室进入。 为得到尽多宝藏,他希望安排一条路线,使走过的不同藏宝宫室尽可能多。请你告诉 DQS 这条路 线最多行经不同藏宝宫室的数目。

输入描述
第一行给出三个正整数 N, R, C。
以下 N 行,每行给出一扇传送门的信息,包含三个正整数
xi, yi, Ti,表示该 传送门设在位于第 xi 行第 yi 列的
藏宝宫室,类型为 Ti。
Ti 是一个 1~3 间的整数,
1 表示可以传送到第 xi 行任意一列的“横天门” ,
2 表示可以传送到任意一行第 yi 列的“纵寰门” ,
3 表示可以传送到周围 8 格宫室的“自由门” 。
保证 1≤xi≤R,1≤yi≤C,所有的传送门位置互不相同。

输出描述
只有一个正整数,表示你确定的路线所经过不同藏宝 宫室
的最大数目。

样例输入
10 7 7
2 2 1
2 4 2
1 7 2
2 7 3
4 2 2
4 4 1
6 7 3
7 7 1
7 5 2
5 2 1

样例输出
9
数据范围及提示
测试点编号 N R C
1 16 20 20
2 300 1,000 1,000
3 500 100,000 100,0004 2,500 5,000 5,000
5 50,000 5,000 5,000
6 50,000 1,000,000 1,000,000
7 80,000 1,000,000 1,000,000
8 100,000 1,000,000 1,000,000
9 100,000 1,000,000 1,000,000
10 100,000 1,000,000 1,000,000 保证每次询问的数均在序列内

原创粉丝点击