[考试反思]1003csp-s模拟测试58:沉淀

稳住阵脚。

还可以。

至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来。

对拍了,暴力都拍了。挺稳的。

但是其实也有波折,险些被卡内存。

如果内存使用不连续或申请的内存全部使用的话,切记计算内存,一点都不能开大。

T1:

直接根号筛,拿map也能过。

遍历map直接begin和end啊。。。

 1 #include<cstdio>
 2 int Cnt[202];
 3 struct hash_map{
 4     int cnt,fir[10000020],l[6666666],to[6666666],w[6666666];
 5     int &operator[](int x){if(x>Cnt[0])return w[0];int r=x%10000019;
 6         for(int i=fir[r];i;i=l[i])if(to[i]==x)return w[i];
 7         l[++cnt]=fir[r];fir[r]=cnt;to[cnt]=x;return w[cnt];
 8     }
 9 }M;
10 int main(){
11     int m;scanf("%d%d",&Cnt[0],&m);
12     for(int i=1,x;i<=m;++i){
13         scanf("%d",&x);
14         for(int j=1;j*j<=x;++j)if(x%j==0)M[j]++,M[x/j]+=(x!=j*j);
15     }
16     for(int i=1;i<=M.cnt;++i)Cnt[M.w[i]]++;
17     for(int i=1;i<=m;++i)Cnt[0]-=Cnt[i];
18     for(int i=0;i<=m;++i)printf("%d\n",Cnt[i]);
19 }

hash_map 581B

hash_map的数组大小要记得计算空间

T2:

应该都能看出是个背包。

不读错题问题都不大。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int dp[301][90002];
 4 vector<pair<int,int> >V[305];
 5 int main(){
 6     int n,m,v,c,t;memset(dp[0],0x3f,sizeof dp[0]);
 7     scanf("%d%d",&n,&m);dp[0][0]=0;
 8     while(n--)scanf("%d%d%d",&c,&v,&t),V[t].push_back(make_pair(c,v));
 9     for(int t=1;t<=300;++t){
10         for(int v=90000;~v;--v)dp[t][v]=dp[t-1][v];
11         for(int S=0;S<V[t].size();++S){
12             int C=V[t][S].first,W=V[t][S].second;
13             for(int v=90000;v>=W;--v)dp[t][v]=min(dp[t][v],dp[t][v-W]+C);
14         }
15         for(int v=89999;~v;--v)dp[t][v]=min(dp[t][v],dp[t][v+1]);
16     }
17     while(m--)scanf("%d%d",&t,&c),printf("%d\n",upper_bound(dp[t],dp[t]+90001,c)-dp[t]-1);
18 }

稍短 641B

不离线询问的话不要开long long。会MLE。

T3:

好题。

考场上一直在想主席树,以为有50000有70000会卡两个log的。显然没有。

这题要处理对于每一个速度的答案。

先考虑li=1的特殊性质。

我们从大到小的考虑速度,这样的话就是一个不断解锁边的过程。

不断填边,求最长链。和模拟测试40《影子》的并查集做法一模一样。

如果li不是1呢?那就有删边操作了。然而直接做貌似不可撤销。

考虑分治。

如果我们现在要求解速度为1和2时的答案,那么一个暴力的思路就是:

把1能过的所有边连上,求解,撤销。把2能过的所有边连上,求解,撤销。

复杂度是n2的。

我们可以发现上面这个方法存在冗余。如果我们一开始就把1和2的边都连上,在求解1,2时不撤销这些边,就可以快一些了。

我们利用的是线段树的结构,我们现在考虑所有[3,5]的询问,于是加入l<=3&&r>=5的边。

然后是处理3的询问,再加入速度可以接受3的边,求解3,再撤销刚刚加入的这些边就好。。。

然后不断按mid分治下去直到叶节点就是答案。

怎么撤销?

每次修改一个数值时,往一个栈里放修改前的值,然后在线段树处理完某一个节点而回溯时,不断弹栈还原至搜索到线段树该节点之前即可。

倍增LCA并没有被卡T。

然而因为要撤销,所以按照原来那道题打路径压缩并查集是不可行的(过程中修改的点太多),为了保证复杂度,我们采取按秩合并。

按秩合并其实就是把并查集按照深度合并,深度小的往打的里面合并的话那么很大可能总深度不变,或者+1。

只用两棵树深度恰好相等时深度+1,其余时候深度还是原来树的深度。不知道为什么网上给的板子深度数组叫rk。

1 int find(int k){return f[k]==k?k:find(f[k]);}
2 int merge(int a,int b){
3     int A=find(a),B=find(b);
4     if(rk[A]>rk[B])f[B]=A;
5     else f[A]=B,rk[B]+=(rk[A]==rk[B]);
6 }

按秩合并大概的板子

然后就差不多了。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<iostream>
 4 using namespace std;
 5 int n,m,fir[70005],l[140005],to[140005],cnt,ans[70005],u[70005],v[70005],L[70005],R[70005];
 6 void link(int a,int b){l[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt;}
 7 int p1[70005],p2[70005],mx[70005],f[70005][20],F[70007],rk[70005],dep[70005],stans[1500005];
 8 int stp1[1500005],stp2[1500005],stmx[1500005],stF[1500005],strk[1500005],o[1500005],top,ANS;
 9 vector<int>V[1500000];
10 void insert(int p,int l,int r,int i){
11     if(L[i]<=l&&r<=R[i]){V[p].push_back(i);return;}
12     if(R[i]>l+r>>1)insert(p<<1|1,(l+r>>1)+1,r,i);
13     if(L[i]<=l+r>>1)insert(p<<1,l,l+r>>1,i);
14 }
15 int find(int k){return F[k]==k?k:find(F[k]);}
16 void dfs(int p,int fa){
17     f[p][0]=fa;dep[p]=dep[fa]+1;F[p]=p1[p]=p2[p]=p;
18     for(int i=1;i<=18;++i)f[p][i]=f[f[p][i-1]][i-1];
19     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)dfs(to[i],p);
20 }
21 int dt(int a,int b){
22     int sub=dep[a]-dep[b],A=a,B=b;
23     if(sub<0)a^=b^=a^=b,sub=-sub;
24     for(int i=18;~i;--i)if(sub&1<<i)a=f[a][i];
25     if(a==b)return sub;
26     for(int i=18;~i;--i)if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i];
27     return dep[A]+dep[B]-2*dep[f[a][0]];
28 }
29 void copy(int x){++top;o[top]=x;stp1[top]=p1[x];stp2[top]=p2[x];stmx[top]=mx[x];stF[top]=F[x];strk[top]=rk[x];stans[top]=ANS;}
30 void recover(){int x=o[top];mx[x]=stmx[top];F[x]=stF[top];ANS=stans[top];p1[x]=stp1[top];p2[x]=stp2[top];rk[x]=strk[top];--top;}
31 void merge(int i){//printf("merge:%d %d\n",u[i],v[i]);
32     int x=u[i],y=v[i],X=find(x),Y=find(y);
33     int mdt,mp1,mp2,Ldt,Lp,Rdt,Rp,res;
34     if(mx[X]>mx[Y])mdt=mx[X],mp1=p1[X],mp2=p2[X];
35     else mdt=mx[Y],mp1=p1[Y],mp2=p2[Y];
36     Ldt=dt(p1[X],x);res=dt(p2[X],x);
37     if(Ldt>res)Lp=p1[X];else Ldt=res,Lp=p2[X];
38     Rdt=dt(p1[Y],y);res=dt(p2[Y],y);
39     if(Rdt>res)Rp=p1[Y];else Rdt=res,Rp=p2[Y];
40     copy(X);copy(Y);
41     if(rk[X]>rk[Y])X^=Y^=X^=Y;rk[Y]+=(rk[X]==rk[Y]);
42     if(Ldt+Rdt+1>mdt)mx[Y]=Ldt+Rdt+1,p1[Y]=Lp,p2[Y]=Rp;
43     else mx[Y]=mdt,p1[Y]=mp1,p2[Y]=mp2;
44     F[X]=Y;ANS=max(ANS,mx[Y]);//printf("ANS:%d\n",ANS);
45 }
46 void Divide_and_Conquer(int p,int l,int r){int re=top;//printf("%d %d\n",l,r);
47     for(int i=0;i<V[p].size();++i)merge(V[p][i]);
48     if(l==r){ans[l]=ANS;goto ed;}
49     Divide_and_Conquer(p<<1,l,l+r>>1);
50     Divide_and_Conquer(p<<1|1,(l+r>>1)+1,r);
51 ed:    while(top>re)recover();
52 }
53 int main(){//freopen("t3.in","r",stdin);freopen("t3.out","w",stdout);
54     scanf("%d%d",&n,&m);
55     for(int i=1;i<n;++i)scanf("%d%d%d%d",&u[i],&v[i],&L[i],&R[i]),link(u[i],v[i]),link(v[i],u[i]),insert(1,1,n,i);
56     dfs(1,0);Divide_and_Conquer(1,1,n);
57     int v;while(m--)scanf("%d",&v),printf("%d\n",ans[v]);
58 }

稍长

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

时间: 2024-11-05 19:00:32

[考试反思]1003csp-s模拟测试58:沉淀的相关文章

csp-s模拟测试58「Divisors」&#183;「Market」&#183;「Dash Speed」?

A. Divisors 大概平均下来每个数也就几千约数吧....,直接筛 B. Market 可以把时间离线下来, 考试没有想到将询问离线,用数组存算了算只能过200的点,拿了70 事实上背包后直接二分就好... C. Dash Speed 好题,想到以前的一道题影子. 考场用单调队列多QJ了20分,然而没有想到并查集 线段树上分治????? 线段树上的节点表示在该权值在该区间内的边,每个节点开个vector即可 那么考虑区间查询和单点修改, 对于每个叶子节点,我们从上到下所经历的边其实就是可行

csps模拟测试58

T1: 这好似我是乱搞过的. 和正解很像. 对于这些数,只有他们的因数才能对答案做贡献,别的都是0. 所以我就可以把每个数分解因数,然后把因数卡在一起. 没有的就是0,统计一下就完了. T2: 考试想到了没时间搞了, 做过一次. 条件答案互换,然后这回球出来的是花费必须为s的最少,你可以让花费至少是s的最少,然后就单调了,直接二分就行了. T3: 限制维护链并的题, 也做过一个, 先看到题中给的询问的范围和n同级. 所以可以考虑线段树分治,就是把边的取值打到线段树上, 然后dfs整棵树,让它在此

模拟测试58

T1: 每个数至多有$2 \sqrt{m}$个约数,也就是说即使$n$很大,在数集中有倍数的数在$m \sqrt{a}$级别. 可以暴力筛出数集中每个数得约数,用hash表维护一下,可实现$O(1)$查询. 用$n$减去筛出的数个数即为答案中0的个数,但是注意超过$n$的数要删掉. 时间复杂度$O(m \sqrt{m})$. T2: 我们发现每个物品的花费很大,价值却很小,于是我们可以将价值做背包,求出每个花费对应的最小代价. 然后将询问离线排序,从时间较早的计划做起. 将所有商店也排序,从早到

[考试反思]0929csp-s模拟测试55:沦陷

菜得过分. 面对T1的大板子不知所措,然后T2的贪心不小心把排序语句删了... T1这种大模板啊...其实我是觉得我能打出来的,然后先用一个小时码了一个2k. 然后做T2想贪心就出来了.十分钟码完T3暴力之后回T1打对拍瞬间爆炸. 于是又重新打了一个2k,WA0.对拍发现. 然后考试就没几分钟了交暴力走了. 不要打完就跑,记得早点对拍改进思路. T1: 的确是挺裸的线段树.离散化或者权值线段树都可以. 但是考场上两个都打出来都死了. 最后用离散化A的. 1 #include<cstdio> 2

[考试反思]1002csp-s模拟测试56:凌乱

放假回来状态回升??(玩够了-但是稍困) T1打的不完全对,但是过掉了.很快的想到了二分吧喇叭啦.. 然后T2也挺快想出来了但是挂细节没发现,考试快结束的时候才发现出锅了. 改了过来是正解,但是出题人无良卡了线段树强制树状数组,T了一个子任务,卡常到飞起. T3暴力没什么问题. 卡常是一种习惯.要注意题目数据范围观察是否卡常. T1: 所有的决策都是一条一次函数. 分两类,斜率正或斜率非负. 如果第二类的直线里有在T=0时符合要求的,那么答案就是0,所以check(0)一下. 如果非负的直线都在

[考试反思]0114省选模拟7:迷离

这次考得相对不错,但是没什么水准. 只不过记得T1这道原题而已.虽说我忘了怎么做,而且数据范围不一样...差不多是从头想的. 但是并没有AC,像个弱智一样,有两个细节写的完全不对还有80分运气也是真好. 其实挂了不止两个细节...以为是原题于是上来就写20分钟写完,然后过一会出一个锅... 然后看T2,感觉$O(nk^2)$也许差不多?常数很大...但也不会别的.挺好想但是不是很好写. 于是乎强烈谴责cbx没素质暴力水题考后还不改正解的无脸行径 于是就开始写,写了一个半小时. 看T3,绝对大神题

模拟测试68,69

68: 32 AlpaCa 41 03:08:20 31 02:46:16 30 02:46:28 102 03:08:20 69: 28 AlpaCa 20 02:51:15 60 03:05:32 0 01:39:45 80 03:05:32 彻底挂掉了呢. 不过也还好吧,至少之后的考试不会有那么大压力了吧(出第一机房是肯定的事了),那利用之后几场考试就调整好状态,下次再来嘛. 但是最近炸了那么多场还是要反思一下,其实不只是心态的问题,自身实力,考试技巧,时间分配等方面好像都有点问题. 69

微信在线信息模拟测试工具(基于Senparc.Weixin.MP)

目前为止似乎还没有看到过Web版的普通消息测试工具(除了官方针对高级接口的),现有的一些桌面版的几个测试工具也都是使用XML直接请求,非常不友好,我们来尝试做一个“面向对象”操作的测试工具. 测试工具在线DEMO:http://weixin.senparc.com/SimulateTool Senparc.Weixin.MP是一个开源的微信SDK项目,地址:https://github.com/JeffreySu/WeiXinMPSDK (其中https://github.com/Jeffrey

2016年上半年软考真题在线模拟测试,提前知晓你的成绩

2016年上半年软考于5月21日结束了,考试完想知道结果的急切心理,几乎每个经历过上学时代的人都能深刻体验到.如果你想知道你考的怎么样,如果你想要提前知道你的成绩,如果你想知道你哪个地方出错了,如果你想知道你哪个地方知识掌握的不够想要更深入的去理解,那就来希赛软考学院吧!希赛软考学院提供2016年上半年软考真题在线模拟测试,有标准的参考答案,有专业老师的解析视频,让你提前知晓你的成绩,让你再次巩固学习. 希赛授课专家介绍 张友生,计算机应用技术博士,软考培训教程系列丛书主编,考试指定教材<系统分