【20170903】模拟赛

卡片(card)

【题目描述】

lrb喜欢玩卡牌。他手上现在有n张牌,每张牌的颜色为红绿蓝中的一种。现在他有两种操作。一是可以将两张任意位置的不同色的牌换成一张第三种颜色的牌;二是可以将任意位置的两张相同颜色的牌换成一张该颜色的牌。两个操作后都可以将生成的牌放到任意位置。现在他想知道,最后一张牌可能是什么颜色的。

【输入描述】

第一行输入一个,表示卡牌数量。

第二行输入一个由’B’,’G’,’R’组成的长度为n的字符串,分别表示卡牌的颜色为蓝色、绿色、红色中的一种。

【输出描述】

输出’B’,’G’,’R’中的若干个字母,按字典序输出。代表可能的最后一张牌的颜色。

【样例】


输入1


输出1


2

RB


G


输入2


输出2


3

GRG


BR


输入3


输出3


4

BBBB


B

【数据范围】

对于100%的数据,n<=200

这是一道很简单的判断题。。。。。。主要就是根据每个字母出现的次数进行判断。

#include<iostream>
#include<cstdio>
using namespace std;
int n,num[4],a,x,y;
char c,d;
bool ans[4];
int main(){
    freopen("card.in","r",stdin);
    freopen("card.out","w",stdout);
    scanf("%d",&n);
    if(n==0) return 0;
    for(int i=1;i<=n;i++){
        cin>>c;
        if(c==‘B‘) {a+=num[1]==0;num[1]++;d=‘B‘;}
        if(c==‘G‘) {a+=num[2]==0;num[2]++;d=‘G‘;}
        if(c==‘R‘) {a+=num[3]==0;num[3]++;d=‘R‘;}
    }
    if(a==3) {printf("BGR\n");return 0;}
    if(a==1) {cout<<d<<endl;return 0;}
    for(int i=1;i<=3;i++){
        if(num[i]) x==0?x=i:y=i;
        if(!num[i]) ans[i]=1;
    }
    if(num[x]>1&&num[y]==1) ans[y]=1;
    if(num[x]==1&&num[y]>1) ans[x]=1;
    if(num[x]>1&&num[y]>1) ans[x]=ans[y]=1;
    if(ans[1]) printf("B");
    if(ans[2]) printf("G");
    if(ans[3]) printf("R");
    puts("");
    return 0;
}

取数(win)

【题目描述】

lrb目前有n个数字,他想知道这n个数中选出若干个数,平均数减中位数的最大值是多少。可以证明,对于一个递增数列a,如果是平均数aw减中位数最大时的中位数,l表示在w两边分别取相邻数字的数量,f(w,l)表示以aw为中位数,在w两侧各取相邻l个数时平均数减中位数的值,那么f(w,l)为关于l的单峰函数。

【输入描述】

第一行为n,为数字个数。

第二行有n个数,分别代表n个数字。

【输出描述】

输出一个数,为平均数减中位数的最大值,保留两位小数。

【样例】


输入


输出


4

1 2 3 4


0.33

【数据范围】

对于60%数据,n<=21

对于75%的数据,n<=2000

对于100%的数据,n<=10^5,0<=ai<=10^6

根据题目显而易见,只可能取奇数个,不然aw不存在

对于偶数个数,假设中间的两个是x1和x2(x1<=x2),平均数为s,所以显然x1和x2不可能都比s大;

(1) x1,x2<=s,那么如果去掉x2,中位数变小,s变大,方案更优;

(2)x1<=s<=x2,那么如果去掉x2,中位数减少x2-x1/2,s减少x2-s/n-1,显然x2-s/n-1<=x2-x1/2,方案更优;

所以一定是奇数个。

为了使平均数尽可能大,我们要取得数是:

因为是个单峰函数,我们可以用三分法来求它的峰值。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define MN 200000
#define ll long long
using namespace std;
int n,a[MN+5];
ll pre[MN+5];
int l,r,mid1,mid2,ansi,ansl;
double ansv,v1,v2;
double f(int i,int l){
    ll sum=0;
    sum+=pre[i]-pre[i-l-1];
    sum+=pre[n]-pre[n-l];
    return (double)sum/(double)(2*l+1)-(double)a[i];
}
int main(){
    freopen("win.in","r",stdin);
    freopen("win.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]); pre[i]=pre[i-1]+a[i];
    }
    sort(a+1,a+n+1);
    if(n<=2) {printf("0.00\n");return 0;}  //特判
    for(int i=1;i<=n;i++){   //枚举中位数
        l=0; r=min(i-1,n-i);
        while(l+1<=r){  //三分
            mid1=l+(r-l)/3; mid2=r-(r-l)/3;
            v1=f(i,mid1); v2=f(i,mid2);
            if(v1>v2) r=mid2-1; else l=mid1+1;
        }
        double v=f(i,l);  //更新
        if(v>ansv){ansv=v; ansi=i; ansl=l;}
    }
    printf("%.2lf\n",ansv);
    return 0;
}

密码(key)

【题目描述】

lrb去柜员机取钱,并输入了他的四位密码。但是这一切都被一个黑帮拍摄了下来。幸好,这一次他的银行卡里并没有剩余任何钱。lrb知道了他的账户被异常登录后十分害怕,然后修改了他的密码。从此以后他为了不被看出密码,他开始“徐晃”。但这一切还是被拍摄了下来,拍摄多次以后,这个黑帮找到了你,希望你在一秒内帮他算出lrb的可能使用的密码数量。

【输入描述】

第一行输入一个n,为lrb被拍摄的动作次数。

接下来n行,每行第一个数为t,表示lrb接下来的手指移动次数,接下来为一个长度为t的数字串,表示lrb手指经过的轨迹。lrb手指经过的位置,可能没有按,也有可能按了多次。

【输出描述】

输出一行,为可能的密码数量。

【样例】


输入


输出


2

3 123

3 234


5


解释


lrb可能用的是2222,2223,2233,2333,3333五种密码

【数据范围】

设所有轨迹串的总长度为L。

对于35%的数据,L<=5000

对于100%的数据,1<=n<=1000,1<=t<=10^4,L<=10^6

把所有的串拼在一起,可以在O(10L)的时间内预处理出对于每一位向后的第一个某个数字的位置。

用f[i][j]表示从第i个位置(包括i(因为可以多次按同一个键))向后查找j数(0~9)的位置,不存在设为1000000,再令f[1000000][0~9]=10000000

然后就可以暴力枚举每种密码后用的O(n)时间进行check,从第0号位置开始。用f[0][第一位的数]跳到下一个位置,接着用f[刚刚跳到的位置][第二位的数]继续跳,以此类推。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[1000005];
int n,t[1005],f[1000005][10];
int main(){
    freopen("key.in","r",stdin);
    freopen("key.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%s",&t[i],s+t[i-1]);
        t[i]+=t[i-1];
    }
    for(int i=0;i<10;i++) f[t[n]][i]=t[n];
    for(int i=t[n]-1;i>=0;i--){
        memcpy(f[i],f[i+1],sizeof f[i+1]);
        f[i][s[i]-‘0‘]=i;
    }
    int x,ans=0;
    for(int a=0;a<10;a++) for(int b=0;b<10;b++)
    for(int c=0;c<10;c++) for(int d=0;d<10;d++){
        x=0;
        for(int i=1;i<=n;i++)
        if(f[f[f[f[t[i-1]][a]][b]][c]][d]<t[i]) x++;
        ans+=x/n;
    }
    printf("%d",ans);
    return 0;
}

三角之恋(tri)
【题目描述】
给出平面上的n个等腰直角三角形。每个三角形用3个整数描述x, y, m(m > 0)。一个三角
形的 3个顶点分别是(x, y),(x + m, y)和(x, y + m)。
你的任务是计算这些三角形覆盖的总面积。

【数据范围】

对于100%的数据,n<=5000,|xi,yi|<=5*10^8,1<=mi<=10^9

解决这题需要离散化并用扫描线。

首先需要离散每个三角形的(x,y),(x+m,y)(x,y+m)三个点,以便于后面计算答案。

然后我们将每个三角形记做一个只有底部线段,并且右端点不断向缩小的线。在更新时直接暴力排序每个线段并踢出会被某个其他线段覆盖的线段,然后将y坐标不断往上推,在过程中暴力计算每个离散长方形的面积,如果某个长方形没被完全覆盖,那么就减去没覆盖的部分的面积。这样就可以在O(n^2)的时间复杂度内算出答案。

嗯没有时间了,只能贴标程了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct sth
{
    int x,y,x2,m,tx,ty;
}l[5005];
    int n,lx,ly,ls,th;
    int X[10005],Y[10005];
    sth S[10005];
    bool u[10005];
    ll ans;
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;
}
bool cmp(sth l1,sth l2)
{
    if (l1.y!=l2.y) return l1.y<l2.y;
    if (l1.x!=l2.x) return l1.x<l2.x;
    return l1.tx<l2.tx;
}
void cal()
{
    int to=Y[th+1]-Y[th],ri;
    for (int i=S[1].x,j=1;X[i]<=S[ls].x2;i++)
    {
        while (j<ls&&i>=S[j+1].x) j++;
        if (X[i]>=S[j].x2) continue;
        ri=min(X[i+1],S[j].x2);
        ans+=2LL*(ri-X[i])*to;
        if (ri>S[j].x2-to)
        {
            if (X[i]<S[j].x2-to)
            {
                int l=ri-(S[j].x2-to);
                ans-=(ll)l*l;
            }
            else
            {
                ans-=(ll)(ri-X[i])*(ri-X[i]);
                int l=X[i]-(S[j].x2-to);
                ans-=2LL*l*(ri-X[i]);
            }
        }
    }
    th++;
    for (int i=1;i<=ls;i++)
        if (S[i].ty<=th) u[i]=false;
        else
        {
            u[i]=true;
            S[i].x2=X[S[i].tx]-(Y[th]-Y[S[i].y]);
        }
    int L=ls;ls=0;
    for (int i=1;i<=L;i++)
        if (u[i]) S[++ls]=S[i];
}
int main()
{
    freopen("tri.in","r",stdin);
    freopen("tri.out","w",stdout);
    n=read();
    for (int i=1;i<=n;i++)
    {
        l[i].x=read(),l[i].y=read(),l[i].m=read();
        X[++lx]=l[i].x,X[++lx]=l[i].x+l[i].m;
        Y[++ly]=l[i].y,Y[++ly]=l[i].y+l[i].m;
    }
    sort(X+1,X+lx+1);
    sort(Y+1,Y+ly+1);
    lx=unique(X+1,X+lx+1)-X-1;
    ly=unique(Y+1,Y+ly+1)-Y-1;
    Y[ly+1]=2e9;X[lx+1]=2e9;
    for (int i=1;i<=n;i++)
    {
        l[i].tx=lower_bound(X+1,X+lx+1,l[i].x+l[i].m)-X;
        l[i].ty=lower_bound(Y+1,Y+ly+1,l[i].y+l[i].m)-Y;
        l[i].x=lower_bound(X+1,X+lx+1,l[i].x)-X;
        l[i].y=lower_bound(Y+1,Y+ly+1,l[i].y)-Y;
        l[i].x2=X[l[i].tx];
    }
    sort(l+1,l+n+1,cmp);
    l[n+1].y=ly+1;
    S[ls=1]=l[1];th=l[1].y;S[0].x2=-2e9;
    for (int i=2;i<=n+1;i++)
    {
        while (ls&&l[i].y>th)
            cal();
        if (th<l[i].y) th=l[i].y;
        bool found=false;
        for (int j=1;j<=ls;j++)
            if (l[i].x<S[j].x)
            {
                if (l[i].x2<=S[j-1].x2) break;
                for (int k=ls;k>=j;k--) S[k+1]=S[k];
                S[j]=l[i];int L=ls+1;ls=j;
                for (int k=j+1;k<=L;k++)
                    if (S[k].x2>S[j].x2) S[++ls]=S[k];
                found=true;
            }
        if (!found&&l[i].x2>S[ls].x2) S[++ls]=l[i];
    }
    if (ans&1) printf("%I64d.5",ans/2);
    else printf("%I64d.0",ans/2);
    return 0;
}


来自PaperCloud的博客,未经允许,请勿转载,谢谢。

时间: 2024-11-05 22:04:08

【20170903】模拟赛的相关文章

【BZOJ】【2741】【FOTILE模拟赛】L

可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成[某个区间中 max(两个数的异或和)] 要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了:然而我们并不能. 一个常见的折中方案:分块! 这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值. 我们不预处理所有的左端点,我

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=

bzoj 2741: 【FOTILE模拟赛】L 分塊+可持久化trie

2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1116  Solved: 292[Submit][Status] Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r. 为了体现在线操作,对于一个询问(x,y):

9.14 模拟赛

模拟赛第三弹~ T1 题意:给你一个数列,要求删掉任意一种整数,使得剩下的新数列中连续的相等的数最多 例如 2 7 3 7 7 3 3 7 7 5 7,删掉3以后剩的7有四个连续的,最多 思路:暴力枚举去掉哪个......这算是一道水题吧 代码丢了...... TAT T2 题意:有n本书,每本书有宽度和高度.现在你有无数个书架,每个书架的宽度为w,高度由最高的书决定 问在书本按顺序放的情况下,总的书架高度最小是多少 思路:dp,dp[i]表示做到第i本书时的最小高度和. 每次先找到能以编号j的

2014-9-9 NOIP模拟赛

东方幻想乡系列模拟赛Stage 1命题 Nettle审题 Barty ccy1991911 FlanS39 Wagner T2 高精除高精,从来没写过,不知道怎么写,我就用大数减小数ans次,果断超时. T4 Tarjan的板子题,好久没写,中间出现了一些小错误 ①是尽管有双向边,Tarjan函数中也不必排除双向边 ②Tarjan算法有时候不能一步完成,需要做最多n次,用循环解决 ③问题是关于这个题目的虽然输入n代表有n个点,但是下面的连边中有些点根本没出现过,所以设一个数组记录有效点. Pro

【题解】PAT团体程序设计天梯赛 - 模拟赛

由于本人愚笨,最后一题实在无力AC,于是只有前14题的题解Orz 总的来说,这次模拟赛的题目不算难,前14题基本上一眼就有思路,但是某些题写起来确实不太容易,编码复杂度有点高~ L1-1 N个数求和 设计一个分数类,重载加法运算符,注意要约分,用欧几里得算法求个最大公约数即可. 1 #include <cstdio> 2 3 long long abs(long long x) 4 { 5 return x < 0 ? -x : x; 6 } 7 8 long long gcd(long

20161027模拟赛解题报告

20161027模拟赛解题报告 By shenben T1 数学题 模拟即可. 注意开long long T2 技巧题 图片为本题第一张图.(无奈,图传不上来) 首先第一问图中的“Y 字形”的数量,这么简单,在此不细讲. 详见代码 O(n)累加一下就好了 主要说说第二问怎么搞 预处理 每个点分别与其他那些点相连 权值为第1,2,3大(若没有2,3大,就忽略).记录一下权值与对应的点的标号.目的是方便下面的判断. 枚举入度>=3的点,即点B(有多个) 再枚举点B相连的D点(不是点A,C). Ste

[GRYZ]寒假模拟赛

写在前面 这是首次广饶一中的OIERS自编自导,自出自做(zuo)的模拟赛. 鉴于水平气压比较低,机(wei)智(suo)的WMY/XYD/HYXZC就上网FQ下海找了不少水(fei)题,经过他们优(le)美(se)的文字加工后,有故事有题目有人物有奸情的模拟赛正式呈上. 我是正文 题目名 GRYZ娱乐时刻 GRYZ追击时刻 GRYZ就餐时刻 源文件 hyxzc.cpp/c/pas clikar.cpp/c/pas eat.cpp/c/pas 输入文件 hyxzc.in clikar.in ea

【简单思考】noip模拟赛 NTR酋长

NTR酋长 (ntr.pas/.c/.cpp) 黄巨大终于如愿以偿的进入了czy的后宫中……但是czy很生气……他要在黄巨大走到他面前的必经之路上放上几个NTR酋长来阻挡黄巨大. 众所周知,NTR酋长有一个技能是沟壑(F).它会在地图上产生一条长长的障碍物阻挡人前进.Czy打算在一个n*m的矩形(必经之路?)中放上NTR酋长.NTR酋长要一个一个放下去,而且每放一个都会向四角倾斜的方向放出无限长的沟壑,而已经被沟壑挡住的地方就不能再放NTR酋长了. 请注意:不会出现沟壑的路径挡住另一个沟壑的情况

【noip模拟赛】 射击

这题似乎是什么安阳一中的模拟题,不管了,反正是学长出的noip模拟赛里面的题目.... 射击(shoot.pas/.c/.cpp) 时间限制:1s,内存限制128MB 题目描述: 据史书记载,对越反击战时期,有位中国侦察兵,他的代号叫814.一天他执行狙击任务,他的任务地区是n座恰巧在一条直线上的山.这些山所在直线恰巧为东西走向,山从东到西依次编号为1~n.一天814隐藏在编号为k的山上,每座山上都有1个目标. 814也非常的厉害,任务结束时杀了很多人,可是史书中只记载了两点: 1:814一定攻