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

[考试反思]0509省选模拟92:警示

时间:2020-05-09 22:58:39      阅读:54      评论:0      收藏:0      [点我收藏+]

标签:puts   long   define   time   none   ons   color   ide   进制   

技术图片

技术图片

同一种低错能犯不知道多少次。就应该有个人在我每次弱智的时候骂我一顿不然真是不长脑子。

$50$分$50$分的挂。。。(虽说牛更惨直接把绿框挂丢了

莫队排序$x.l/B<x.l/B$。$y$呢?

然后就直接$T$成暴力。亏得我还写了对拍,没有试大测试点。(暴力跑不出来)

之前就有一次因为对拍没有试大数据爆炸了,

但愿能长记性吧。。。

本来是拿下构造剩下暴力写满的。构造题有多解但是最开始没有$spj$我人都傻了

(最近构造题好多。貌似终于发现了第一个我比较擅长的题型。。。或许也不好说。。。菜死了

耽误了不少时间而且把心态弄得有点炸。。。$T1$那玩意都做烂了还没想出正解的确可能受到了一定影响

再说了。。。根号算法就那么几个咋每次都用不好。。。

反正状态不是很好。。。下次还要调整啊。。。

 

T1:Mansion

大意:有$n$个点,每个点有权值$a_i,b_i$。多次询问$\max\limits_{i=vl}^{vr} (\sum\limits_{j=l}^{r} b_j [a_j = i] ) $。$n,m,q \le 1.5 \times 10^5$

被牛嘲讽了。

是个类似于区间众数的问题。这种问题最低复杂度也就是$O(n^{1.5})$了

学过的根号就那么几种,所以不难想到莫队。维护线段树即可。复杂度是$O(\sqrt{n} log n)$的。

然后在莫队中,修改次数是$O(n\sqrt{n})$的但是查询次数是$O(n)$的,

所以根号平摊一下,分块$O(1)$修改$O(\sqrt{n})$查询就行了。

然而不支持删除。那就把莫队回滚一下。

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int S=150005,B=400;
 4 struct Qs{int l,r,vl,vr,o;friend bool operator<(Qs x,Qs y){return x.l/B!=y.l/B?x.l/B<y.l/B:x.r<y.r;}}Q[S];
 5 int n,m,q,a[S],b[S],p[S],t;long long w[S],c[S],ans[S],wv[S],cv[S];
 6 #define lc p<<1
 7 #define rc p<<1|1
 8 #define md (L+R>>1)
 9 void add(int x,int v,int op){
10     if(op)p[++t]=x,wv[t]=w[x],cv[t]=c[x/B];
11     w[x]+=v; c[x/B]=max(c[x/B],w[x]);
12 }
13 long long ask(int l,int r,long long a=0){
14     if(l/B==r/B)for(int i=l;i<=r;++i)a=max(a,w[i]);
15     else{
16         for(int i=l;i<l/B*B+B;++i)a=max(a,w[i]);
17         for(int i=r;i>=r/B*B;--i)a=max(a,w[i]);
18         for(int i=l/B+1;i<r/B;++i)a=max(a,c[i]);
19     }return a;
20 }
21 void clear(){while(t)w[p[t]]=wv[t],c[p[t]/B]=cv[t],t--;}
22 int main(){//freopen("1.in","r",stdin);freopen("1.out","w",stdout);
23     scanf("%d%d%d",&n,&m,&q);
24     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
25     for(int i=1;i<=n;++i)scanf("%d",&b[i]);
26     for(int i=1;i<=q;++i)scanf("%d%d%d%d",&Q[i].l,&Q[i].r,&Q[i].vl,&Q[i].vr),Q[i].o=i;
27     Q[0].l=-B; sort(Q+1,Q+1+q);
28     for(int l=1,r=0,i=1;i<=q;++i){
29         if(Q[i].l/B!=Q[i-1].l/B){
30             l=Q[i].l/B*B+B;r=l-1;
31             for(int i=1;i<=m;++i)w[i]=c[i]=0;
32         }
33         if(Q[i].l/B==Q[i].r/B){
34             for(int j=Q[i].l;j<=Q[i].r;++j)add(a[j],b[j],1);
35             ans[Q[i].o]=ask(Q[i].vl,Q[i].vr);
36             clear(); continue;
37         }
38         while(r<Q[i].r)++r,add(a[r],b[r],0);
39         while(l>Q[i].l)--l,add(a[l],b[l],1);
40         ans[Q[i].o]=ask(Q[i].vl,Q[i].vr);
41         clear(); l=Q[i].l/B*B+B;
42     }for(int i=1;i<=q;++i)printf("%lld\n",ans[i]);
43 }
View Code

 

T2:Permutation

大意:给定一个陪列,每次操作可以选定一些元素,被选中的元素放到所有没选中的元素之后,且选中的和未选中的元素内部相对顺序不变。

要求最小化变为元排列的步数以及构造方案。$n \le 5 \times 10^4$

对于任意两个元素$a,b$,不妨设$a<b$

若在一开始$a$就在$b$前面,那么在每次操作中,两个数所经历的是否被选中的状态可以完全相同。

如果被选中是$1$不被选中是$0$,那么对于每个数经历的操作会形成一个$01$串,如$w_a$(注意是针对数说的,而不是针对下标)

若$a<b,ia<ib$则$w_a$可以等于$w_b$

然后考虑如果$w_a \neq w_b$有哪些可能。

如果操作序列不完全相同的话,最终两元素的相对位置由 最后一次两者选中状态不同的那次操作中谁被选中了 决定。

具体而言,如果最后一次不同是在操作$i$,则若$a<b$则$w_{a,i} = 0 ,w_{b,i}=1$

我们发现这样的话,我们把二进制串理解成二进制数的话(后面的操作为高位前面的操作是低位)

那么就是说,若$a<b$且$w_a \neq w_b$则$w_a < w_b$

整理得到对于任意$a<b$,若$p_a < p_b$则$w_a \le w_b$,否则$w_a < w_b$

这样我们就得到了$n^2$个限制关系。没法做。

考虑到谁在谁前面 这种关系是有传递性的,最后我们要构造的是元排列,那么只要$1$在$2$前面,$2$在$3$前面。。。$n-1$在$n$前面就足够了

不再需要$1$在$3$前面这种限制。那么现在就只剩下了$n-1$条限制。整理如下:

$0 \le w_1 <= w_2 <= w_3 <= ... <= w_n <2^{ans}$

其中的$<=$可能被替换为$<$或$\le$。为了最小化$ans$我们一定会在所有可以和前面一个值取等的地方取等,不能取等就只$+1$

显然是最优的。这样就得到了所有的$w$。$ans$和方案也就显然了。

技术图片
 1 #include<cstdio>
 2 #define S 55555
 3 int p[S],ip[S],n,ord,ans,v[S],op,q1[S],q2[S],t1,t2;
 4 int main(){
 5     scanf("%d%d",&n,&op);
 6     for(int i=1;i<=n;++i)scanf("%d",&p[i]),ip[p[i]]=i;
 7     for(int i=n-1;i;--i)v[i]=ip[i]>ip[i+1]?++ord:ord;
 8     while(1<<ans<=ord)ans++;
 9     printf("%d\n",ans);
10     if(!op)return 0;
11     for(int i=1;i<=n;++i)v[i]=ord-v[i];
12     for(int i=1;i<=n;++i)printf("%d ",p[i]);puts("");
13     while(ans--){
14         t1=t2=0;
15         for(int i=1;i<=n;++i)if(v[p[i]]&1)q1[++t1]=p[i],v[p[i]]>>=1;
16             else q2[++t2]=p[i],v[p[i]]>>=1;
17         for(int i=1;i<=t2;++i)printf("%d ",p[i]=q2[i]);
18         for(int i=1;i<=t1;++i)printf("%d ",p[i+t2]=q1[i]); puts("");
19     }
20 }
View Code

 

T3:Grid Game

由于太菜咕掉了。去看牛神的博客吧。

 

[考试反思]0509省选模拟92:警示

标签:puts   long   define   time   none   ons   color   ide   进制   

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

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