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
",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;
}