• 正睿 2018 普及组5连测 Day2


    前言:这一周算比较良心吧...(小伙速度还是要提快一点a.....)

    T1:

    一个比较简单的模拟题,所以才更要注重细节啊......

    需要注意的一点,求两个矩形相交的面积

    设矩形1左下角点坐标为(x1,y1)右上角点坐标为(x2,y2)

    设矩形2左下角点坐标为(x3,y3)右上角点坐标为(x4,y4)

    记minx=max(x1,x3),miny=max(y1,y3),maxx=min(x2,x4),maxy=min(y2,y4)

    矩形1,2相交的条件是minx<maxx并且miny<maxy

    满足则相交面积为(maxx-minx)*(maxy-miny);

    其他就没什么了,模拟一定要注意细节,稳住心态,忌焦忌躁,可以现在纸上列出需要执行的事项,一项项执行,心态心态心态!

    上代码:

     1 #include<bits/stdc++.h>
     2 #define maxn 2005
     3 typedef long long ll;
     4 using namespace std;
     5 struct node{
     6     ll p,x,y;
     7     ll w;
     8     ll h;
     9     int id;
    10 }nd[maxn];
    11 bool cmp(node a,node b){
    12     return a.p>b.p;
    13 }
    14 bool vis[maxn];
    15 int n,a,st[maxn],top=0,a1,a2,a3,a4;
    16 ll check(ll x,ll y,ll w,ll h,ll xx,ll yy,ll ww,ll hh){
    17     ll s;
    18     ll minx=max(x-w,xx-ww);
    19     ll miny=max(y-h,yy-hh);
    20     ll maxx=min(x+w,xx+ww);
    21     ll maxy=min(y+h,yy+hh);
    22     if(minx<maxx&&miny<maxy) s=(maxx-minx)*(maxy-miny);//即使为负也没什么关系 
    23     else s=0;
    24     
    25     return s;
    26 }
    27 void init(){
    28     scanf("%d",&n);
    29     int pos=0;
    30     int tt=n;//防O2优化
    31     for(int i=1;i<=tt;i++){
    32         scanf("%lld",&a);
    33         int t=a/100000;
    34         if(t<6){
    35         scanf("%d%d%d%d",&a1,&a2,&a3,&a4);    
    36         continue;
    37         }
    38         ++pos;
    39         scanf("%lld%lld%lld%lld",&nd[pos].x,&nd[pos].y,&nd[pos].w,&nd[pos].h);//注意这里是半长半高 
    40         nd[pos].p=a;
    41         nd[pos].id=i;
    42     }
    43     int poss=1;
    44     int cnt=pos;
    45     sort(nd+1,nd+pos+1,cmp);
    46     while(cnt){
    47         cnt--;
    48         while(vis[nd[poss].id]&&poss<=pos) poss++;
    49         vis[nd[poss].id]=1;
    50         st[++top]=nd[poss].id;
    51         ll x=nd[poss].x,y=nd[poss].y,w=nd[poss].w,h=nd[poss].h;
    52         poss++;
    53         for(int i=poss;i<=pos;i++){
    54             if(!vis[nd[i].id]){
    55                 ll xx=nd[i].x,yy=nd[i].y,ww=nd[i].w,hh=nd[i].h;
    56                 ll cd=check(x,y,w,h,xx,yy,ww,hh);
    57                 ll s=(w*2)*(h*2),ss=(ww*2)*(hh*2);
    58                 ll bin=s+ss-cd,jiao=cd;
    59                 if((2*jiao)>bin){
    60                     vis[nd[i].id]=1;cnt--;
    61                 }
    62             }
    63         }
    64     }
    65     sort(st+1,st+top+1);
    66     for(int i=1;i<=top;i++) printf("%d ",st[i]);
    67 }
    68 int main(){
    69     init();
    70     
    71     return 0;
    72 }

    T2:

    比较简单的dp题(考试时人工记录了每个字母对应的情况,可以冷静下用电脑计入快一些)

    设状态dp[i][0/1]表示前i个电码是否以'Z'结尾表示的种数

    为了使不出现‘ZR’两个字符,只在匹配到R的时候不计入dp[i-1][1]即可

    转移方程:if(j==26) dp[pos-1][1]=(dp[pos-1][1]+dp[i-1][0]+dp[i-1][1])%mod;

    else if(j!=18) dp[pos-1][0]=(dp[pos-1][0]+dp[i-1][0]+dp[i-1][1])%mod

    else dp[pos-1][0]=(dp[pos-1][0]+dp[i-1][0])%mod;//注:pos-1为当前匹配到的位置

    上代码:

     1 #include<bits/stdc++.h>
     2 #define maxn 1000005
     3 using namespace std;
     4 typedef long long ll;
     5 const ll mod=1e9+7;
     6 ll dp[maxn][2];
     7 char mp[30][7];
     8 char s[maxn];
     9 void ready(){
    10     mp[1][1]='0',mp[1][2]='1',mp[2][1]='1',mp[2][2]='0',mp[2][3]='0',mp[2][4]='0',mp[3][1]='1',mp[3][2]='0',mp[3][3]='1',mp[3][4]='0',mp[4][1]='1',mp[4][2]='0',mp[4][3]='0',mp[5][1]='0',mp[6][1]='0',mp[6][2]='0',mp[6][3]='1',mp[6][4]='0',mp[7][1]='1',mp[7][2]='1',mp[7][3]='0',mp[8][1]='0',mp[8][2]='0',mp[8][3]='0',mp[8][4]='0',mp[9][1]='0',mp[9][2]='0',mp[10][1]='0',mp[10][2]='1',mp[10][3]='1',mp[10][4]='1',mp[11][1]='1';
    11     mp[11][2]='0',mp[11][3]='1',mp[12][1]='0',mp[12][2]='1',mp[12][3]='0',mp[12][4]='0',mp[13][1]='1',mp[13][2]='1',mp[14][1]='1',mp[14][2]='0',mp[15][1]='1',mp[15][2]='1',mp[15][3]='1',mp[16][1]='0',mp[16][2]='1',mp[16][3]='1',mp[16][4]='0',mp[17][1]='1',mp[17][2]='1',mp[17][3]='0',mp[17][4]='1',mp[18][1]='0',mp[18][2]='1',mp[18][3]='0',mp[19][1]='0',mp[19][2]='0',mp[19][3]='0',mp[20][1]='1',mp[21][1]='0',mp[21][2]='0',mp[21][3]='1',mp[22][1]='0',mp[22][2]='0',mp[22][3]='0',mp[22][4]='1',mp[23][1]='0',mp[23][2]='1',mp[23][3]='1',mp[24][1]='1',mp[24][2]='0',mp[24][3]='0',mp[24][4]='1',mp[25][1]='1',mp[25][2]='0',mp[25][3]='1',mp[25][4]='1',mp[26][1]='1',mp[26][2]='1',mp[26][3]='0',mp[26][4]='0';
    12 }
    13 void dpp(){
    14     int len=strlen(s+1);
    15     dp[0][0]=1;int pos;
    16     for(int i=1;i<=len;i++){
    17         for(int j=1;j<=26;j++){
    18             pos=i;
    19             bool ok=true;
    20             while(mp[j][pos-i+1]){
    21                 if(mp[j][pos-i+1]!=s[pos]||pos>len){
    22                     ok=false;break;
    23                 }
    24                 pos++;
    25             }
    26             if(ok){
    27             if(j==26) dp[pos-1][1]=(dp[pos-1][1]+dp[i-1][0]+dp[i-1][1])%mod;
    28             else if(j!=18) dp[pos-1][0]=(dp[pos-1][0]+dp[i-1][0]+dp[i-1][1])%mod;    
    29             else dp[pos-1][0]=(dp[pos-1][0]+dp[i-1][0])%mod;    
    30             }
    31         }
    32     }
    33     printf("%lld",(dp[len][0]+dp[len][1])%mod);
    34 }
    35 int main(){
    36     ready();
    37     scanf("%s",s+1);
    38     dpp();
    39     
    40     return 0;
    41 } 

    T3:

    emmmmmmm这道题海星,首先必须意识到符号相同的几个单位之间可以使用交换律和结合律,而根据题目,可知几个单位合并的最小代价需要贪心,即合并果子,这里用堆实现即可。所以dfs一遍,遇到不同符号的就得计算。细心实现即可。上代码:

     1 //并行计算
     2 #include<bits/stdc++.h>
     3 #define maxn 500005
     4 using namespace std;
     5 typedef long long ll;
     6 char opp[maxn];
     7 int op[maxn],fa[maxn*2],n,x,y;
     8 ll wj,wc;
     9 struct eage{
    10     int to,next;
    11 }e[maxn<<1];
    12 int np=0,first[maxn];
    13 void add(int u,int v){
    14     e[++np]=(eage){v,first[u]};
    15     first[u]=np;
    16 }
    17 ll st[maxn*2];
    18 int top=0;
    19 struct noded{
    20     ll w;
    21     friend bool operator <(noded a,noded b){
    22         return a.w>b.w;
    23     } 
    24 };
    25 void dfs(int now,int pre){
    26     int topp=top;
    27     if(now>=n){st[++top]=0;return;}
    28     
    29     for(int p=first[now];p;p=e[p].next){
    30         int j=e[p].to;
    31         dfs(j,op[now]);
    32     }
    33     
    34     if((op[now]^pre)||pre==-1){
    35         priority_queue<noded>q;
    36         while(top!=topp) q.push((noded){st[top--]});
    37         while(23333){
    38             noded i=q.top();q.pop();
    39             if(q.empty()){
    40                 st[++top]=i.w;
    41                 break;
    42             }
    43             noded ii=q.top();q.pop();
    44             ll ww=max(ii.w,i.w)+(op[now]==1?wj:wc);
    45             q.push((noded){ww}); 
    46         }
    47     }    
    48     
    49 }
    50 void init(){
    51     scanf("%d%lld%lld",&n,&wj,&wc);
    52     scanf("%s",opp);
    53     for(int i=1;i<=n-1;i++) op[i]=(opp[i-1]=='+'?1:0);//标记 
    54     for(int i=1;i<=2*n-2;i++){
    55         scanf("%d%d",&x,&y);
    56         add(x,y);
    57         fa[y]=x; 
    58     }
    59     int root;
    60     for(int i=1;i<=2*n-1;i++) if(fa[i]==0){root=i;break;}
    61     
    62     dfs(root,-1);
    63     printf("%lld",st[top]);
    64 }
    65 int main(){
    66     init();
    67     
    68     return 0;
    69 } 

    T4:

    这道题比较复杂a....要推很多式子,注意细节....

    首先想到应该是二分,然后主要check函数:如果我们知道其他人票数v·,以及席位个数x那么(这个不能编辑公式aqwq)可以根据题意解一个不等式得到x的最小值然后只要满足∑xi<=m-mid即可。

    f(i,j) 表考虑了前 i 个政党(第1个除外)留给下一个政党还剩 j 票(就是 ai 中分配给第 i + 1 个政党 j 票),前 i 个政党的 xi 之和最小是多少。 

    随后观察数据范围,将j表示还剩的票与选得的位置交换(很Nice的思路)令f(i,j)表考虑了前 i 个政党(第1个除外)的 xi 之和是j,留给下一
    个政党 i + 1 的票数最少是多少。 //这里运用贪心,下一个最少则席位最少。
    这个时候对于每一个i,会获得从前面来的f票,此刻为满足只占x个席位可通过不等式求出再多拿票的最大值(这样剩的票就少)枚举每个xi就行。

    上代码:

     1 //席位选举
     2 #include<bits/stdc++.h>
     3 #define maxn 55
     4 #define maxm 505
     5 using namespace std;
     6 typedef long long ll; 
     7 int n,m,a[maxn],v[maxn],dp[maxn][maxm];
     8 bool check(int mid){
     9     memset(dp,0x3f,sizeof(dp));
    10     dp[1][0]=0;
    11     for(int i=1;i<n-1;i++){//前i个选了j个席位 
    12         for(int j=0;j<=m;j++){
    13             for(int k=0;j+k<=m;k++){
    14                 if (v[1]*(k+1)/mid-v[i+1]-dp[i][j]>=0)
    15               dp[i+1][j+k]=min(dp[i+1][j+k],max(0,a[i+1]-(v[1]*(k+1)/mid-v[i+1]-dp[i][j])));
    16             } 
    17         }
    18     }
    19     ll ans=1LL<<60;
    20     for (int j=0;j<=m;j++){
    21     int vi=v[n]+dp[n-1][j];
    22     ll s=max(0LL,((ll)mid*vi-1)/v[1]);
    23     ans=min(ans,j+s);
    24     }
    25     return ans<=m-mid;
    26 }
    27 void run(){
    28     int L=0,R=m+1,mid;
    29     while (L+1<R)
    30     if (check(mid=(L+R)>>1))
    31       L=mid;
    32     else
    33       R=mid;
    34   printf("%d
    ",L);
    35 }
    36 void init(){
    37     scanf("%d%d",&n,&m);
    38     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
    39     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    40     v[1]=v[1]+a[1]+a[n];
    41     run();
    42 }
    43 int main(){
    44     init(); 
    45     
    46     return 0;
    47 } 

    细致...读题清楚...速度...

     

  • 相关阅读:
    WPF中从资源中检索指定路径的图片文件
    Prometheus
    py2exe的安装和使用
    .net HttpWebRequest发送cookie失败
    贷款计算测试
    关于input清空之后组件试图不更新解决办法 emmiter.js dispatch使用
    JS对象对象构造器
    【golang笔记】字符串
    MYSQL 字符集
    2022年2月的一些碎碎念
  • 原文地址:https://www.cnblogs.com/degage/p/9690640.html
Copyright © 2020-2023  润新知