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('\n');
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('\n');
114 //    FOR(i,1,n-1) FOR(j,i,n) printf("[%d,%d]=%d\n",i,j,f[i][j]);
115     return 0;
116 }
View Code

猜你喜欢

转载自www.cnblogs.com/C-S-X/p/11784854.html