【20170902校内模拟赛】

T1 卡片(card)

Description

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

Input

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

Output

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

Sample Input 1

2
RB

Sample Output 1

G

Sample Input 2

3
GRG

Sample Output 2

BR

Sample Input 3

4
BBBB

Sample Output 3

B

Hint

对于100%的数据,n≤200

Solution

各种特判就行了。。。分支结构题

Code

#include <stdio.h>
#define R register
#define Filename "card"
inline int read(){
	R int x; R bool f; R char c;
	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
	return f?-x:x;
}
int T[3],n,cnt,B[3];
int main(){
#ifndef Debug
	freopen(Filename".in","r",stdin);
	freopen(Filename".out","w",stdout);
#endif
	n=read();
	for (R int i=1; i<=n; ++i){
		R char c=getchar();
		while(c<'A'||c>'Z') c=getchar();
		if (c=='B') ++T[0];
		if (c=='G') ++T[1];
		if (c=='R') ++T[2];
	}
	for (R int i=0; i<3; ++i) cnt+=(T[i]>1),B[i]=(T[i]>1);
	if (cnt>1) puts("BGR");
	else{
		if (T[0]&&T[1]&&T[2]) puts("BGR");
		else{
			if (!cnt){
				for (R int i=0; i<3; ++i) cnt+=(bool)(T[i]);
				if (cnt==1){
					if (T[0]) puts("B");
					if (T[1]) puts("G");
					if (T[2]) puts("R");
				}else{
					if (T[0]&&T[1]) puts("R");
					if (T[0]&&T[2]) puts("G");
					if (T[1]&&T[2]) puts("B");
				}
			}else{
				R int p=-1;
				for (R int i=0; i<3; ++i){
					if (B[i]) cnt=i;
					if (T[i]==1) p=i;
				}
				if (p==-1){
					if (cnt==0) puts("B");
					if (cnt==1) puts("G");
					if (cnt==2) puts("R");
				}else{
					if (cnt==0) puts("GR");
					if (cnt==1) puts("BR");
					if (cnt==2) puts("BG");
				}
			}
		}
	}
#ifndef Debug
	fclose(stdin); fclose(stdout);
#endif
	return 0;
}

T2 取数(win)

Description

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

Input

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

Output

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

Sample Input

4
1 2 3 4

Sample Output

0.33

Hint

对于60%的数据,n≤21
对于75%的数据,n≤2000
对于100%的数据,\(n≤10^{5},0≤a_{i} ≤ 10^{6}\)

Solution

显然对于选定的中位数,选取l个比它小的尽量大的数,以及l个比它大的尽量大的数可以使得平均数最优,可以证明这个平均数是关于l的单峰函数,故可以使用三分得出l的最优值,枚举所有中位数即可。
时间效率\(O(n \log_{\frac {3}{2}} n)\).

Code

#include <stdio.h>
#include <algorithm>
#define MN 100005
#define ll long long
#define R register
#define eps 1e-5
#define Filename "win"
inline int read(){
	R int x; R bool f; R char c;
	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
	return f?-x:x;
}
ll f[MN];int n;double ans;
inline int min(int a,int b){return a<b?a:b;}
inline double max(double a,double b){return a-b>eps?a:b;}
inline ll getsum(int k,int l){return f[n]-f[n-l]+f[k]-f[k-l-1];}
int search(int l,int r,int k,int kk){
	if (l==r) return l;
	R int p1=(r-l)/3+l,p2=r-(r-l)/3;
	if (1.0*getsum(k,p2)/(2*p2+kk)-1.0*getsum(k,p1)/(2*p1+kk)>eps) return search(p1+1,r,k,kk);
	return search(l,p2-1,k,kk);
}
int main(){
#ifndef Debug
	freopen(Filename".in","r",stdin);
	freopen(Filename".out","w",stdout);
#endif
	n=read();for (R int i=1; i<=n; ++i) f[i]=read();
	std::sort(f+1,f+n+1);
	for (R int i=2; i<=n; ++i) f[i]+=f[i-1];
	for (R int i=2; i<n; ++i){
		R int tmp=search(1,min(i-1,n-i),i,1);R double ttmp;
		ttmp=1.0*(f[i]-f[i-tmp-1]+f[n]-f[n-tmp])/(2.0*tmp+1.0)-(f[i]-f[i-1]);
		ans=max(ans,ttmp);if (i<n-1){
			tmp=search(1,min(i-1,n-i-1),i,2);
			ttmp=1.0*(f[i+1]-f[i-tmp-1]+f[n]-f[n-tmp])/(2.0*tmp+2.0)-(f[i+1]-f[i-1])/2.0;
			ans=max(ans,ttmp);
		}
	}printf("%.2lf",ans);
#ifndef Debug
	fclose(stdin); fclose(stdout);
#endif
	return 0;
}

T3 密码(key)

Description

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

Input

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

Output

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

Sample Input

2
3 123
3 234

Sample Output

5

Hint

设所有轨迹串的总长度为L。
对于35%的数据,L≤5000;
对于100%的数据,\(1≤n≤1000,1≤t≤10^{4},L≤10^{6}\)

Solution

这道题有一个十分显然简单思路(想不到的都是有病,such as me)
我们只要枚举所有的密码就好了
然后就是如何check一个密码是否成立。
我们只要开一个数组记录从每一位开始,后面的第一个0-9分别在第几位,如果都能够找到,那么密码合法。
如此判断反复判断n次,就可以得到这个密码是否完全成立。
时间复杂度为\(O(10^{4}n)\)

Code

#include <stdio.h>
#define MN 1005
#define ML 1000005
#define R register
#define Filename "key"
inline int read(){
	R int x; R bool f; R char c;
	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
	return f?-x:x;
}
int f[ML][10],ans,n,t[MN]; char c[ML];
int main(){

#ifndef Debug
	freopen(Filename".in","r",stdin);
	freopen(Filename".out","w",stdout);
#endif
	n=read();for (R int i=1; i<=n; ++i) t[i]=read()+t[i-1],scanf("%s",c+t[i-1]);
	for (R int i=0; i<10; ++i) f[t[n]][i]=t[n];
	for(R int i=t[n]-1; i>=0; --i)
		for(R int j=0; j<10; ++j) f[i][j]=f[i+1][j],f[i][c[i]-'0']=i;
	for (R int a=0; a<10; ++a)
		for (R int b=0; b<10; ++b)
			for (R int c=0; c<10; ++c)
				for (R int d=0; d<10; ++d){
					R int cnt=0;for (R int i=0; i<n; ++i) 
						if (f[f[f[f[t[i]][a]][b]][c]][d]<t[i+1]) cnt++;
					ans+=(cnt==n);
				}printf("%d\n",ans);
#ifndef Debug
	fclose(stdin); fclose(stdout);
#endif
	return 0;
}

T4 三角之恋(tri)

Description

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

Input

第一行为n,为三角形个数。
接下来每行三个数\(x_{i},y_{i},m_{i}\),用于描述一个三角形。

Output

输出一个数,为这些三角形覆盖的总面积,保留一位小数。

Sample Input

5
-5 -3 6
-1 -2 3
0 0 2
-2 2 1
-4 -1 2

Sample Output

24.5

Hint

\(n≤5000,|x_{i},y_{i} |≤5*10^{8},1≤m_{i}≤10^{9}\)

Solution

利用一条扫描线,在离散之后的平面内计算。看成一个个长方形,则只有未被覆盖与覆盖两种可能,处理一下即可,时间效率\(O(n^{2})\)

Code

#include <stdio.h>
#include <algorithm>
#define MN 5005
#define R register
#define min(a,b) ((a)<(b)?(a):(b))
#define ll long long
#define inf 0x7fffffff
#define Filename "tri"
inline int read(){
	R int x; R bool f; R char c;
	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
	return f?-x:x;
}
int n,xn,yn,tmp,sn,X[MN<<1],Y[MN<<1];
bool used[MN<<1];ll ans;
struct rt{
	int x,y,m,tx,ty,x2;
}a[MN],s[MN];
inline bool cmp(rt a,rt b){return (a.y<b.y||(a.y==b.y&&(a.x<b.x||(a.x==b.x&&a.tx<b.tx))));}
inline void calc(){
	R int to=Y[tmp+1]-Y[tmp];
	for (R int i=s[1].x,j=1,r; X[i]<=s[sn].x2; ++i){
		while (j<sn&&i>=s[j+1].x) ++j;
		if (X[i]>=s[j].x2) continue;
        r=min(X[i+1],s[j].x2);
        ans+=2ll*(r-X[i])*to;
        if (r>s[j].x2-to){
            if (X[i]<s[j].x2-to){
                R int l=r-(s[j].x2-to);
                ans-=(ll)l*l;
            }
            else{
                ans-=(ll)(r-X[i])*(r-X[i]);
                R int l=X[i]-(s[j].x2-to);
                ans-=2ll*l*(r-X[i]);
            }
        }
	}++tmp;
    for (R int i=1; i<=sn; ++i)
        if (s[i].ty<=tmp) used[i]=0; 
        else{
            used[i]=1;
            s[i].x2=X[s[i].tx]-(Y[tmp]-Y[s[i].y]);
        }
    R int l=sn; sn=0;for (R int i=1; i<=l; ++i)
        if (used[i]) s[++sn]=s[i];
}
int main(){
#ifndef Debug
	freopen(Filename".in","r",stdin);
	freopen(Filename".out","w",stdout);
#endif
	n=read();for (R int i=1; i<=n; ++i){
		a[i].x=read(),a[i].y=read(),a[i].m=read();
		X[++xn]=a[i].x,X[++xn]=a[i].x+a[i].m;
        Y[++yn]=a[i].y,Y[++yn]=a[i].y+a[i].m;
	}std::sort(X+1,X+xn+1);std::sort(Y+1,Y+yn+1);
    xn=std::unique(X+1,X+xn+1)-X-1;yn=std::unique(Y+1,Y+yn+1)-Y-1;
    Y[yn+1]=X[xn+1]=inf;
    for (R int i=1; i<=n; ++i){
    	a[i].tx=std::lower_bound(X+1,X+xn+1,a[i].x+a[i].m)-X;
        a[i].ty=std::lower_bound(Y+1,Y+yn+1,a[i].y+a[i].m)-Y;
        a[i].x=std::lower_bound(X+1,X+xn+1,a[i].x)-X;
        a[i].y=std::lower_bound(Y+1,Y+yn+1,a[i].y)-Y;
        a[i].x2=X[a[i].tx];
	}std::sort(a+1,a+n+1,cmp);a[n+1].y=yn+1;
	s[sn=1]=a[1]; tmp=a[1].y; s[0].x2=-inf;
	for (R int i=2; i<=n+1; ++i){
		while(sn&&a[i].y>tmp) calc();
		if (tmp<a[i].y) tmp=a[i].y;R bool flag=0;
        for (R int j=1; j<=sn; ++j)
            if (a[i].x<s[j].x){
                if (a[i].x2<=s[j-1].x2) break;
                for (int k=sn; k>=j; --k) s[k+1]=s[k];
                s[j]=a[i];int l=sn+1; sn=j;
                for (R int k=j+1; k<=l; ++k)
                    if (s[k].x2>s[j].x2) s[++sn]=s[k];
                flag=1;
            }
        if (!flag&&a[i].x2>s[sn].x2) s[++sn]=a[i];
	}
	if (ans&1) printf("%lld.5",ans/2); else printf("%lld.0",ans/2);
#ifndef Debug
	fclose(stdin); fclose(stdout);
#endif
	return 0;
}
posted @ 2017-09-05 17:13  Melacau  阅读(190)  评论(0编辑  收藏  举报