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


    稳住阵脚。

    还可以。

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

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

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

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

    T1:Divisors

    直接根号筛,拿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
    ",Cnt[i]);
    19 }
    hash_map 581B

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

    T2:Market

    应该都能看出是个背包。

    不读错题问题都不大。

     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
    ",upper_bound(dp[t],dp[t]+90001,c)-dp[t]-1);
    18 }
    稍短 641B

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

    T3:Dash Speed

    好题。

    考场上一直在想主席树,以为有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
    ",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
    ",ANS);
    45 }
    46 void Divide_and_Conquer(int p,int l,int r){int re=top;//printf("%d %d
    ",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
    ",ans[v]);
    58 }
    稍长
  • 相关阅读:
    特性和属性
    装箱和拆箱的问题(NET1.1+)
    poj 1013 Counterfeit Dollar(模拟)
    poj 3686 The Windy's( KM算法 )
    二分匹配(匈牙利算法)
    poj 3273 Monthly Expense(二分)
    poj 2115 C Looooops(扩展欧几里德)
    poj 2400 Supervisor, Supervisee
    poj 2195 Going Home (KM算法)
    poj 2513 Colored Sticks(trie树 + 并查集 + 欧拉图)
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11621301.html
Copyright © 2020-2023  润新知