• 2019正睿CSP-S模拟赛十连测day9


    2019正睿CSP-S模拟赛十连测day9

    link to this contest

    这场由于场外求助了博哥,分数有点水分,原本大概$20+$名,现在是$80+20+40=140(rank=10)$,但还是没能把应该拿的分都拿全啊

    A. 蔡老板

    • 先二分一个答案,考虑如何贪心地判断是否可以
    • 从低位到高位一位一位地考虑,如果这一个是$1$那么在可选集合中选一个最大的,剩下的两个两个打包留到下一层,作为下一层的备选集合
     1 #include<bits/stdc++.h>
     2 #define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
     3 #define For(i,a,b) for (register ll i=(a);i>=(b);i--)
     4 #define mem(i,j) memset(i,j,sizeof(i))
     5 #define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
     6 #define fi first
     7 #define se second
     8 #define pb push_back
     9 #define MP make_pair
    10 #define pii pair<ll,ll>
    11 using namespace std;
    12 typedef long long ll;
    13 const ll N=2e5+5;
    14 ll n,k,L,R,MID,er[60],sum=0,tot;
    15 ll bit[60];
    16 struct data
    17 {
    18     ll a,b;
    19 }f[N],tmp[N];
    20 multiset <data> s;
    21 multiset <data> :: iterator it;
    22 vector <data> vec[60];
    23 bool operator <(data x,data y) {return (x.a==x.a)?(x.b>y.b):(x.a<y.a);}
    24 inline ll read()
    25 {
    26     ll x=0,f=1;
    27     char c=getchar();
    28     while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    29     while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    30     return f*x;
    31 }
    32 inline void write(ll x)
    33 {
    34     if (x<0) putchar('-'),x=-x;
    35     if (x>9) write(x/10);
    36     putchar(x%10+'0');
    37     return;
    38 }
    39 bool cmp(const data x,const data y) {return x.b>y.b;}
    40 inline ll check(ll mid)
    41 {
    42     ll len=0,got=0;
    43     while (mid) {bit[++len]=(mid&1),mid>>=1;}
    44     s.clear();
    45     FOR(i,1,len)
    46     {
    47         FOR(j,0,(ll)vec[i-1].size()-1) s.insert(vec[i-1][j]);
    48         if (bit[i])
    49         {
    50             if (s.size())
    51             {
    52                 it=s.begin();
    53                 got+=(*it).b;
    54                 s.erase(it);
    55             }
    56         }
    57         tot=0;
    58         for (it=s.begin();it!=s.end();it++) tmp[++tot]=(*it);
    59         s.clear();
    60         for (register ll i=1;i+1<=tot;i+=2) s.insert((data){i+1,tmp[i].b+tmp[i+1].b});
    61         if (tot&1) s.insert((data){i+1,tmp[tot].b});
    62     }
    63     return (got>=k);
    64 }
    65 int main()
    66 {
    67 //    freopen("data.in","r",stdin);
    68 //    freopen("myans.out","w",stdout);
    69     er[0]=1;
    70     FOR(i,1,35) er[i]=er[i-1]<<1;
    71     n=read(),k=read();
    72     FOR(i,1,n) f[i].a=read(),f[i].b=read(),sum+=er[f[i].a];
    73     FOR(i,1,n) vec[f[i].a].pb(f[i]);
    74     FOR(i,0,35) sort(vec[i].begin(),vec[i].end(),cmp);
    75     L=0,R=sum;
    76     while (L<R)
    77     {
    78         MID=(L+R)>>1;
    79         if (check(MID)) R=MID;
    80         else L=MID+1;
    81     }
    82     write(L),putchar('
    ');
    83     return 0;
    84 }
    View Code

    B. 唯一睿酱

    • 对于某个区间$[l,r]$,且$l-1$和$r+1$位置上的数都比这之中的要大,如果我们能立马知道这个区间中谁最大,就很好做,相当于给了你笛卡尔树让你求方案,但是现在没给,于是你枚举一下,看看哪些数可能成为最大值,递归到两边,这是个子问题,再乘上组合数即可
    • 考虑我们是如何在区间中找到可能最大值位置的,我们从中间往两边扫,如果有个数恰好碰到的边界,那么它可能成为最大值,并且$break$因为再往旁边的数一定比它小,这个过程我们不难发现,某个区间内可能成为最大值的位置最多只有两个,我们把枚举改为一些预处理的小操作即可
      1 #include<bits/stdc++.h>
      2 #define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
      3 #define For(i,a,b) for (register ll i=(a);i>=(b);i--)
      4 #define mem(i,j) memset(i,j,sizeof(i))
      5 #define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define MP make_pair
     10 #define pii pair<ll,ll>
     11 using namespace std;
     12 typedef long long ll;
     13 const ll N=5050;
     14 const ll mod=1e9+7;
     15 ll n,a[N],f[N][N],ans,L[N],R[N],vis[N];
     16 ll fac[N],inv[N],st1[21][N],st2[21][N];
     17 vector <int> vec[N];
     18 inline ll read()
     19 {
     20     ll x=0,f=1;
     21     char c=getchar();
     22     while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
     23     while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     24     return f*x;
     25 }
     26 inline void write(ll x)
     27 {
     28     if (x<0) putchar('-'),x=-x;
     29     if (x>9) write(x/10);
     30     putchar(x%10+'0');
     31     return;
     32 }
     33 inline ll qpow(ll x,ll y) {ll ret=1;for (;y;y>>=1,x=1LL*x*x%mod) if (y&1) ret=1LL*ret*x%mod;return ret;}
     34 inline void init()
     35 {
     36     fac[0]=1;
     37     FOR(i,1,n) fac[i]=1LL*fac[i-1]*i%mod;
     38     inv[n]=qpow(fac[n],mod-2);
     39     For(i,n-1,0) inv[i]=1LL*inv[i+1]*(i+1)%mod;
     40     return;
     41 }
     42 inline ll C(ll x,ll y) {return 1LL*fac[x]*inv[y]%mod*inv[x-y]%mod;}
     43 inline void upd(ll &x,ll y) {x=(1LL*x+y)%mod;return;}
     44 inline void build_st()
     45 {
     46     FOR(i,1,n) st1[0][i]=L[i],st2[0][i]=R[i];
     47     FOR(j,1,20) FOR(i,1,n-(1<<j)+1)
     48     {
     49         st1[j][i]=min(st1[j-1][i],st1[j-1][i+(1<<(j-1))]);
     50         st2[j][i]=max(st2[j-1][i],st2[j-1][i+(1<<(j-1))]);
     51     }
     52     return;
     53 }
     54 inline int query1(int l,int r)
     55 {
     56     int step=log2(r-l+1);
     57     return min(st1[step][l],st1[step][r-(1<<step)+1]);
     58 }
     59 inline int query2(int l,int r)
     60 {
     61     int step=log2(r-l+1);
     62     return max(st2[step][l],st2[step][r-(1<<step)+1]);
     63 }
     64 inline ll solve(ll l,ll r)
     65 {
     66     if (l>r) return 1;
     67     if (l==r) return f[l][r]=1;
     68     if (f[l][r]!=-1) return f[l][r];
     69     if (query1(l,r)<l) return f[l][r]=0;
     70     if (query2(l,r)>r) return f[l][r]=0;
     71     if (l==3&&r==5)
     72     {
     73         int cut=1;
     74     }
     75     ll sum=0;
     76     FOR(i,0,(int)vec[l].size()-1)
     77     {
     78         int pos=vec[l][i];
     79         if (pos-a[pos]!=l&&pos+a[pos]!=r) continue;
     80         if (pos<l||pos>r) continue;
     81         ll tmp=1LL*solve(l,pos-1)*solve(pos+1,r)%mod*C(r-l,r-pos)%mod;
     82         upd(sum,tmp);
     83         vis[pos]=1;
     84     }
     85     FOR(i,0,(int)vec[r].size()-1)
     86     {
     87         int pos=vec[r][i];
     88         if (pos-a[pos]!=l&&pos+a[pos]!=r) continue;
     89         if (pos<l||pos>r) continue;
     90         if (vis[pos]) continue;
     91         ll tmp=1LL*solve(l,pos-1)*solve(pos+1,r)%mod*C(r-l,r-pos)%mod;
     92         upd(sum,tmp);
     93     }
     94     FOR(i,0,(int)vec[l].size()-1) vis[vec[l][i]]=0;
     95     f[l][r]=sum;
     96     return sum;
     97 }
     98 int main()
     99 {
    100     mem(f,-1);
    101     n=read();
    102     init();
    103     FOR(i,1,n) a[i]=read();
    104     FOR(i,1,n) L[i]=i-a[i],R[i]=i+a[i];
    105     build_st();
    106     FOR(i,1,n) vec[i-a[i]].pb(i),vec[i+a[i]].pb(i);
    107     FOR(i,1,n) 
    108     {
    109         sort(vec[i].begin(),vec[i].end());
    110         vec[i].resize(unique(vec[i].begin(),vec[i].end())-vec[i].begin());
    111     }
    112     ans=solve(1,n);
    113     write(ans),putchar('
    ');
    114 //    FOR(i,1,n-1) FOR(j,i,n) printf("[%d,%d]=%d
    ",i,j,f[i][j]);
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    linux 常用快捷键
    命令行远程链接
    mybatis参数错误 Parameter '×××' not found. Available parameters are [0, 1, param1, param2]
    mybatis延迟加载
    mybatis跨XML引用
    eclipse修改项目名称
    wait, WIFEXITED, WEXITSTATUS
    进程通信中如何进行值得传递?
    fork新建进程
    Ubuntu安装genymotion模拟器步骤
  • 原文地址:https://www.cnblogs.com/C-S-X/p/11784854.html
Copyright © 2020-2023  润新知