2017.09.03校內訓練
T1:卡片
題解:這很明顯,是一道選擇題!!!
我們考慮每一種情況:只有一種卡片時,很顯然最後剩下的只能是這一種;有三種卡片時,可以變成各只有一張,無論選取哪兩張,都可以變成剩下的那一張,因此每一種都可以剩下;有兩種的情況:若這兩種都有兩張以上,便可以各取一張合成沒有的那一種,最後結果請參見上一條;若有一種只有一張,另一種有多張,則每一次的轉化操作都要使用到較多的那種一張,不論如何都不可能合成較多張的那一種。因此結果是除了多於一張的那一種以外的其它兩種;若這兩種各只有一張,則結果必定是沒有的那一種。
代碼:
1 #include<iostream> 2 #include<cstdio> 3card.cpp#include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 struct node{ 9 char ki; 10 int num; 11 }card[5]; 12 int n,kind=0; 13 bool c[5]={}; 14 char s[210]; 15 int main(){ 16 freopen("card.in","r",stdin); 17 freopen("card.out","w",stdout); 18 scanf("%d",&n); 19 scanf("%s",s); 20 int i,j; 21 card[1].ki=‘B‘;card[2].ki=‘G‘;card[3].ki=‘R‘; 22 card[1].num=0;card[2].num=0;card[3].num=0; 23 int x; 24 for(i=0;i<n;++i){ 25 if(s[i]==‘B‘) x=1; 26 if(s[i]==‘G‘) x=2; 27 if(s[i]==‘R‘) x=3; 28 if(card[x].num==0) kind++; 29 card[x].num++; 30 } 31 if(kind==3){ 32 printf("BGR\n"); 33 return 0; 34 } 35 if(kind==1){ 36 if(card[1].num>0) printf("B\n"); 37 if(card[2].num>0) printf("G\n"); 38 if(card[3].num>0) printf("R\n"); 39 return 0; 40 } 41 if(kind==2){ 42 int a,b; 43 if(card[1].num>0){ 44 a=1; 45 if(card[2].num>0) b=2; 46 else b=3; 47 } 48 else{ 49 a=2;b=3; 50 } 51 if(card[a].num>=2 && card[b].num>=2){ 52 printf("BGR\n"); 53 return 0; 54 } 55 if(card[a].num==1 && card[b].num==1){ 56 for(i=1;i<=3;++i){ 57 if(card[i].num==0){ 58 printf("%c\n",card[i].ki); 59 return 0; 60 } 61 } 62 } 63 for(i=1;i<=3;++i){ 64 if(card[i].num<=1) c[i]=true; 65 } 66 for(i=1;i<=3;++i){ 67 if(c[i]==true){ 68 printf("%c",card[i].ki); 69 } 70 } 71 printf("\n"); 72 } 73 return 0; 74 }
T2:取數
題解:我們註意到:取奇數個數的數一定不會比再取一個偶數的結果更劣。而計算平均數的復雜度很高。因此我們考慮枚舉中位數。而取一個中位數,在一個遞增序列中,它左邊的數應當盡量靠近它,右邊的數應當盡量遠離它。因此我們由題目可以得出:可以對於每一個位置三分這個位置的最優解/較優解並更新答案即可。
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<cstring> 7 #define ll long long 8 using namespace std; 9 int n; 10 ll maxw,maxl,l,r,wa,wb; 11 int a[200010]; 12 ll pre[200010]; 13 double va,vb,v,ans=-1; 14 double getans(int w,int l){ 15 ll sum=0; 16 sum+=pre[w]-pre[w-l-1]; 17 sum+=pre[n]-pre[n-l]; 18 return (double)sum/(double)(2*l+1)-(double)a[w]; 19 } 20 int main(){ 21 freopen("win.in","r",stdin); 22 freopen("win.out","w",stdout); 23 scanf("%d",&n); 24 int i,j,k; 25 for(i=1;i<=n;++i){ 26 scanf("%d",&a[i]); 27 } 28 sort(a+1,a+n+1); 29 pre[0]=0; 30 for(i=1;i<=n;++i){ 31 pre[i]=pre[i-1]+a[i]; 32 } 33 if(n<=2){ 34 printf("0.00\n");return 0; 35 } 36 for(i=1;i<=n;++i){ 37 l=0;r=min(i-1,n-i); 38 while(l+1<=r){ 39 wa=l+(r-l)/3; 40 wb=r-(r-l)/3; 41 va=getans(i,wa); 42 vb=getans(i,wb); 43 if(va>vb){ 44 r=wb-1; 45 } 46 else l=wa+1; 47 } 48 v=getans(i,l); 49 if(v>ans){ 50 ans=v; 51 maxw=i; 52 maxl=l; 53 } 54 } 55 printf("%.2lf",ans); 56 return 0; 57 }win.cpp
T3:密碼
題解:我們註意到,因為可能出現的密碼種類只有10000種。所以我們先用O(10L)的時間來預處理出對於每一位向後的第一個某數字的位置。之後在O(10000)的時間內枚舉密碼,對於每一個密碼,可以在O(n)的時間裏check,最後統計進模板裏即可。
代碼:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 char ch[1000010]; 9 int l[1010]; 10 int n,a,b; 11 int f[1000010][20]; 12 int main(){ 13 freopen("key.in","r",stdin); 14 freopen("key.out","w",stdout); 15 int i,w,h,z,j; 16 scanf("%d",&n); 17 l[0]=0; 18 for(i=1;i<=n;++i){ 19 scanf("%d%s",&l[i],ch+l[i-1]); 20 l[i]+=l[i-1]; 21 } 22 for(i=0;i<=9;++i) f[l[n]][i]=l[n]; 23 for(i=l[n]-1;i>=0;--i){ 24 memcpy(f[i],f[i+1],sizeof f[i+1]); 25 f[i][ch[i]-48]=i; 26 } 27 a=0;b=0; 28 for(w=0;w<=9;++w){ 29 for(h=0;h<=9;++h){ 30 for(z=0;z<=9;++z){ 31 for(j=0;j<=9;++j){ 32 for(i=0;i<n;++i){ 33 if(f[f[f[f[l[i]][w]][h]][z]][j]<l[i+1]) ++a; 34 else break ; 35 } 36 b+=a/n;a=0; 37 } 38 } 39 } 40 } 41 printf("%d\n",b); 42 return 0; 43 }key.cpp
T4:三角之戀
題解:我們可以從題目中看出這些信息:由於我們所要加入平面中的三角形都是等腰直角三角形,因此對於每一個單位長度的正方形,若其被覆蓋,則只會存在兩種情況:完全覆蓋與過對角線覆蓋一半。因此我們考慮采用離散化+掃描線的方式做。
首先我們需要離散每個三角形的(x,y),(x+m,y),(x,y+m)三個點,便於後面計算答案。
然後我們將每個三角形記作一個只有底部線段,並且右端點不斷向左端點縮小的線段。在更新時直接暴力排序並且剔除會被某個其他線段覆蓋的線段,然後將y坐標不斷向上推,在過程中暴力計算每個離散長方形的面積,如果某個長方形沒有被完全覆蓋,那麽就減去沒覆蓋的部分的面積。這樣就可以在O(n2)的時間復雜度內計算出答案。
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #define ll long long 8 using namespace std; 9 struct node{ 10 int x,y,m,xb,tx,ty; 11 }tri[5010]; 12 int n,lx,ly,ls,th; 13 int x[10010],y[10010]; 14 node s[10010]; 15 bool u[10010]; 16 ll ans; 17 bool cmp(node a,node b){ 18 if(a.y!=b.y) return a.y<b.y; 19 if(a.x!=b.x) return a.x<b.x; 20 return a.tx<b.tx; 21 } 22 void work(){ 23 int to=y[th+1]-y[th],r; 24 int i,j=1; 25 for(i=s[1].x;x[i]<=s[ls].xb;++i){ 26 while(j<ls && i>=s[j+1].x) ++j; 27 if(x[i]>=s[j].xb) continue ; 28 r=min(x[i+1],s[j].xb); 29 ans+=2LL*(r-x[i])*to; 30 if(r>s[j].xb-to){ 31 if(x[i]<s[j].xb-to){ 32 int l=r-(s[j].xb-to); 33 ans-=(ll)l*l; 34 } 35 else{ 36 ans-=(ll)(r-x[i])*(r-x[i]); 37 int l=x[i]-(s[j].xb-to); 38 ans-=2LL*l*(r-x[i]); 39 } 40 } 41 } 42 th++; 43 for(i=1;i<=ls;++i){ 44 if(s[i].ty<=th) u[i]=false; 45 else{ 46 u[i]=true; 47 s[i].xb=x[s[i].tx]-(y[th]-y[s[i].y]); 48 } 49 } 50 int k=ls;ls=0; 51 for(i=1;i<=k;++i){ 52 if(u[i]) s[++ls]=s[i]; 53 } 54 } 55 int main(){ 56 freopen("tri.in","r",stdin); 57 freopen("tri.out","w",stdout); 58 scanf("%d",&n); 59 int i,j,k; 60 for(i=1;i<=n;++i){ 61 scanf("%d%d%d",&tri[i].x,&tri[i].y,&tri[i].m); 62 x[++lx]=tri[i].x;x[++lx]=tri[i].x+tri[i].m; 63 y[++ly]=tri[i].y;y[++ly]=tri[i].y+tri[i].m; 64 } 65 sort(x+1,x+lx+1);sort(y+1,y+ly+1); 66 lx=unique(x+1,x+lx+1)-x-1; 67 ly=unique(y+1,y+ly+1)-y-1; 68 y[ly+1]=2e9;x[lx+1]=2e9; 69 for(i=1;i<=n;++i){ 70 tri[i].tx=lower_bound(x+1,x+lx+1,tri[i].x+tri[i].m)-x; 71 tri[i].ty=lower_bound(y+1,y+ly+1,tri[i].y+tri[i].m)-y; 72 tri[i].x=lower_bound(x+1,x+lx+1,tri[i].x)-x; 73 tri[i].y=lower_bound(y+1,y+ly+1,tri[i].y)-y; 74 tri[i].xb=x[tri[i].tx]; 75 } 76 sort(tri+1,tri+n+1,cmp); 77 tri[n+1].y=ly+1; 78 ls=1;s[ls]=tri[1];th=tri[1].y;s[0].xb=-2e9; 79 for(i=2;i<=n+1;++i){ 80 while(ls && tri[i].y>th) work(); 81 if(th<tri[i].y) th=tri[i].y; 82 bool found=false; 83 for(j=1;j<=ls;++j){ 84 if(tri[i].x<s[j].x){ 85 if(tri[i].xb<=s[j-1].xb) break ; 86 for(k=ls;k>=j;--k) s[k+1]=s[k]; 87 s[j]=tri[i]; 88 int lr=ls+1;ls=j; 89 for(k=j+1;k<=lr;++k){ 90 if(s[k].xb>s[j].xb) s[++ls]=s[k]; 91 } 92 found=true; 93 } 94 } 95 if(!found && tri[i].xb>s[ls].xb) s[++ls]=tri[i]; 96 } 97 if(ans&1){ 98 printf("%lld.5",ans/2); 99 } 100 else printf("%lld.0",ans/2); 101 return 0; 102 }tri.cpp
2017.09.03校內訓練