码迷,mamicode.com
首页 > 其他好文 > 详细

[考试反思]0329省选模拟57:细节

时间:2020-03-30 09:51:06      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:考试   细节   rac   int   直接   close   线段树   div   多项式   

技术图片

技术图片

最近细节总是挂总是挂总是挂。我说我$T2$估分$62$有人信吗?

有没有人信不重要。反正是没拿到。而且直接爆零了。

原因是变量名写反了且少了一种情况(想到了忘写了)。这怕不是个弱智吧。。。

大样例看起来挺大的,然后都跑过了,我以为不说$62$,$48$也应该是稳了。

时间分配还是奇奇怪怪的,反正就是莫名的时间不够。

$T2$研究了好久,$T3$也想了挺长时间。

然后一直觉得$T1$很神仙(看数据范围不像什么常规的多项式复杂度$dp$,没往状压上想)于是最后只给它留了半小时左右。

然后发现,好像出题人说它是签到题这是真的,于是就开始写,发现复杂度好像有点高(然而其实已经$AC$了)

于是剩下的时间都拿去剪枝卡常什么的,再也没有看一眼我爆零的$T2...$

改题的时候又自闭了。因为有下发数据于是一直没有写对拍,但是下发数据又太大,于是一直干瞪着。

然后问别人也大都不给我看于是磨磨蹭蹭将近$6$小时就过去了。

结果最后还是对拍小数据发现了问题,然后就$A$掉了。

考后对拍也是真有用啊。。。

 

T1:Max

大意:初始为空的序列$A$长为$n$。$m$轮操作第$i$轮有$p_{i,j,k}$的概率使得$A_j + = k$。其中$0\le k \le c$

求所有操作后整个序列最大值的期望。$n \le 40,c‘le 3 ,m \le 10$

数据范围小的奇怪。$m$在状压范围内。

于是就状压$m$表示这个子集的轮是否已经被分配给其它人。做一个背包$dp$就行了。

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define mod 1000000007
 4 int n,m,c,p[55][11][5],dp[1025][33],bp[1025][33],t[33],ans,bt[1025],pre[1025][33];
 5 int main(){//freopen("max3.in","r",stdin);
 6     cin>>n>>m>>c;
 7     for(int i=1;i<=m;++i)for(int j=1;j<=n;++j)for(int k=0;k<=c;++k)scanf("%d",&p[j][i][k]);
 8     const int mst=(1<<m)-1;
 9     for(int i=1;i<=mst;++i)bt[i]=bt[i^i&-i]+c;
10     dp[mst][0]=1;
11     for(int i=1;i<=n;++i){
12         memset(bp,0,sizeof bp);memset(pre,0,sizeof pre);
13         for(int s=mst;~s;--s){
14             bp[s][0]=1;
15             for(int j=1;j<=m;++j)if(s&1<<j-1){
16                 for(int y=0;y<=bt[s];++y)for(int x=0;x<=c;++x)t[y+x]=(t[y+x]+1ll*bp[s][y]*p[i][j][x])%mod;
17                 for(int y=0;y<=bt[s];++y)bp[s][y]=t[y],t[y]=0;
18             }
19             pre[s][0]=bp[s][0];
20             for(int y=1;y<=bt[s];++y)pre[s][y]=(pre[s][y-1]+bp[s][y])%mod;
21         }
22         for(int s=1;s<=mst;++s)for(int x=0;x<=bt[mst^s];++x)if(dp[s][x])
23             for(int u=s;u;u=u-1&s){
24                 dp[s^u][x]=(dp[s^u][x]+1ll*dp[s][x]*pre[u][min(bt[u],x)])%mod;
25                 for(int y=x+1;y<=bt[u];++y)dp[s^u][y]=(dp[s^u][y]+1ll*dp[s][x]*bp[u][y])%mod;
26             }
27     }for(int i=1;i<=bt[mst];++i)ans=(ans+1ll*i*dp[0][i])%mod; cout<<ans<<endl;
28 }
View Code

 

T2:paint

大意:$w\times h$的矩阵中有$n$特殊点,要求选定一个周长最大的矩形使得其内部不含特殊点(不含边框)。$n\le 10^5,w,h \le 10^8$

发现任意一个$1\times h$或$w \times 1$的矩形都一定合法。所以答案大于等于$(max(w,h)+1)\times 2$

所以说它一定越过了$x=\frac{x}{2}$或$y=\frac{h}{2}$。以前者为例,做扫描线,枚举矩形右边界。

用一个线段树维护每个点作为左端点的收益,即维护$max(-l+u-d)$。然后可以发现$u,d$的取值关于左端点单调,形式是单调栈。

所以就这么维护一下,线段树区间加全局$max$。要注意各种边界。

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 611111
 4 unordered_map<int,int>X; vector<int>Y[S];
 5 int n,w,h,ans,rx[S],x[S],y[S],u[S],ul[S],ut,d[S],dl[S],dt,v[S<<2],lz[S<<2],c,z,H;
 6 #define lc p<<1
 7 #define rc lc|1
 8 #define md (L+R>>1)
 9 void build(int p,int L,int R){lz[p]=0;
10     if(L==R){v[p]=-rx[L];return;}
11     build(lc,L,md); build(rc,md+1,R); v[p]=max(v[lc],v[rc]);
12 }
13 void add(int l,int r,int w,int p=1,int L=0,int R=c){if(r<l)return;//f(p==1)cerr<<l<<‘ ‘<<r<<‘ ‘<<w<<endl;
14     if(l<=L&&R<=r){v[p]+=w;lz[p]+=w;return;}
15     if(lz[p])v[lc]+=lz[p],v[rc]+=lz[p],lz[lc]+=lz[p],lz[rc]+=lz[p],lz[p]=0;
16     if(l<=md)add(l,r,w,lc,L,md); if(r>md)add(l,r,w,rc,md+1,R); v[p]=max(v[lc],v[rc]);
17 }
18 void solve(){
19     memset(rx,0,sizeof rx);
20     H=h/2; n=z; X.clear();
21     for(int i=1;i<=z;++i)rx[i]=x[i],x[++n]=x[i],y[n]=0,x[++n]=x[i],y[n]=h;
22     x[++n]=w;y[n]=0; x[++n]=0;y[n]=0; x[++n]=0;y[n]=h; x[++n]=w;y[n]=h; rx[n-1]=0; rx[n]=w;
23     sort(rx+1,rx+1+n); c=unique(rx+1,rx+1+n)-rx-1;
24     for(int i=1;i<=c;++i)X[rx[i]]=i;
25     for(int i=1;i<=n;++i)Y[X[x[i]]].push_back(y[i]);
26     build(1,0,c); 
27     u[0]=H; d[0]=H+1; ut=dt=0;
28     for(int r=1;r<=c;++r){
29         add(r-1,r-1,h);ans=max(ans,rx[r]+v[1]);add(r-1,r-1,-h);
30         for(int a:Y[r])if(a<=H){
31             if(dl[dt]==r&&d[dt]>=a)continue;
32             while(d[dt]<=a)add(dl[dt-1],dl[dt]-1,d[dt]),dt--;
33             add(dl[dt],r-1,-a);d[++dt]=a;dl[dt]=r;
34         }else{
35             if(ul[ut]==r&&u[ut]<=a)continue;
36             while(u[ut]>=a)add(ul[ut-1],ul[ut]-1,-u[ut]),ut--;
37             add(ul[ut],r-1,a);u[++ut]=a;ul[ut]=r;
38         }Y[r].clear();
39     }
40 }
41 int main(){
42     cin>>w>>h>>n; z=n;
43     for(int i=1;i<=z;++i)scanf("%d%d",&x[i],&y[i]);
44     solve(); for(int i=1;i<=z;++i)swap(x[i],y[i]); swap(h,w); solve();
45     cout<<ans*2<<endl;
46 }
View Code

 

T3:Decompose

大意:将树剖分成若干长度$\le L$的链,对于每条链,其中深度第$i$大的点$p$会贡献$w[p][i]$。最大化整棵树的贡献。

每次单点修改权值之后,进行回答。$n ,qL \le 10^5,2 \le L \le 4$

看一眼就知道是$ddp$。一如既往的难写。由于$T2$调太久了就没时间写了。

首先暴力肯定就是$dp[p][i]=\sum\limits_{u \in son(p)} (\max\limits_{j=1}^{L} dp[u][j]) + \max\limits_{u \in son(p)} (f[p][i-1] - (\max\limits_{j=1}^{L} dp[u][j]))$

然后那个$max$可以用$set$维护。暴跳父亲复杂度是$O(n^2logn)$的。

然后套个$ddp$的板子把上面这玩意轻重儿子分开弄一个矩阵时间复杂度就变成$qlog^2nL^3+nL^3$

 

[考试反思]0329省选模拟57:细节

标签:考试   细节   rac   int   直接   close   线段树   div   多项式   

原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12595188.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!