zoukankan      html  css  js  c++  java
  • [考试反思]0203省选模拟17:庸碌

    又有原题。所以还是4.5h4道题。

    0+60+15+4=79。rk15。

    考了个x啊这是。

    这次出咕咕咕估分功能了(真的咕了好久啊)

    估分是这样的:0+60+50+100=210

    T4是原题。

    当时我乱搞AC了。考后又打了一遍正解又A了一遍。

    于是上报了,教练说不打正解的直接给0分。

    然而KDtree是不是正解我不知道,复杂度高但是可以过。反正我也不会,我的乱搞被卡了而已。

    正解思路还记得挺清晰。但是实现的时候忘赋初值了。。。

    诶不是现在的样例怎么都是可以乱过的啊。。。

    实际数据下只过了n=1。。。。

    估分100实际4。。。真。。。

    %%%miku又一次写了KDtree,然后剪枝后精确估分92

    省选重题好多啊。。。就题面改了一点,连数据都没换。。。

    T3是原题强化。数据都出满了所以估50肯定是高了,但是没有锅的话应该是30

    然而15分。。。

    第一次尝试用了一下NC极力推荐的加减函数,然后把加减写反了。。。

    是MT的加边。我那么一弄变成边加点减了。。。

    然后很奇妙,对于n是偶数的测试点我的答案都负了过去。

    测试点保证n=5/6/7/8/9/10各一个点,所以我精确的拿到3个有15分。。。

    幸亏这个暴力数据没出满不然就真爆零了。。。

    后两题这么一折腾就剩下70分钟左右。。。看着T2的部分分多就直接上来就打

    稳稳的打到60再高的也没想。。。然后惊奇的成为4题里分最高的一个

    最后给T1剩下了40分钟。想到了正解(虽然麻烦但是可以AC的)剩下的时间也就二十多分钟了。

    暴写,将近3k。写完,过编译,调RE,然后开始弄样例。。。

    时间还是没赶上。最后交个没过样例的上去信仰跑自觉估分0

    其实没差多少了就有一个细节忘写了

    然后就垫底了。。。

    改题还是很顺利。。。毕竟考场上的思路都差不太多。。。

    只不过T2突然被xm问住发现自己少证了,不过后来又被miku教会了。

    顺便把咕咕咕的昨天T3给弄掉了,cin被卡常了23333

    T1:选择

    大意:图,支持删边,查询两点是否在一个环内。$n,m,q le 100000$

    删边?

    时光倒流。

    环,加边?

    像生成树。

    链修改,链查询?

    树剖,线段树。

    维护在一个环内?

    并查集。

    然后这题就没了。但是代码还是很麻烦。

    仔细想一想不难发现线段树其实是弱智行为,直接记录并查集顶端的点然后暴跳。

    在同一个并查集上的点在树上当然是一个联通块。。。

    暴跳复杂度少个log,常数也小,代码也好写。。。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 666666
     4 int n,m,q,dt[S],f[S],dfn[S],tim,top[S],fir[S],l[S],to[S],ec,sz[S],hson[S],w[S],idfn[S];
     5 int dep[S],U[S],V[S],te[S],tf[S],ans[S];char o[S][2];
     6 unordered_map<int,int>M[S];unordered_set<int>s,rs;
     7 struct ed{
     8     int x,y,t,o;
     9     friend bool operator<(ed a,ed b){return a.t>b.t;}
    10 }E[S];
    11 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
    12 void dfs(int p,int F){
    13     sz[p]=1;f[p]=F;dep[p]=dep[F]+1;
    14     for(int i=fir[p];i;i=l[i])if(to[i]!=F){
    15         dfs(to[i],p);sz[p]+=sz[to[i]];
    16         if(sz[to[i]]>sz[hson[p]])hson[p]=to[i];
    17     }
    18 }
    19 void DFS(int p,int tp){
    20     dfn[p]=++tim;top[p]=tp;idfn[tim]=p;
    21     if(hson[p])DFS(hson[p],tp);
    22     for(int i=fir[p];i;i=l[i])if(to[i]!=f[p]&&to[i]!=hson[p])DFS(to[i],to[i]);
    23 }
    24 #define lc p<<1
    25 #define rc lc|1
    26 #define md (cl+cr>>1)
    27 void build(int p,int cl,int cr){
    28     if(cl==cr){w[p]=idfn[cl];return;}
    29     build(lc,cl,md);build(rc,md+1,cr);
    30 }
    31 void chg(int l,int r,int v,int p=1,int cl=1,int cr=n){
    32     if(l<=cl&&cr<=r){w[p]=v;return;}
    33     if(l<=md)chg(l,r,v,lc,cl,md);
    34     if(r>md)chg(l,r,v,rc,md+1,cr);
    35     w[p]=w[lc]==w[rc]?w[lc]:0;
    36 }
    37 void ask(int l,int r,int p=1,int cl=1,int cr=n){
    38     if(w[p]){s.insert(w[p]);return;}
    39     if(l<=md)ask(l,r,lc,cl,md);
    40     if(r>md)ask(l,r,rc,md+1,cr);
    41 }
    42 void upd(int a,int b,int v){
    43     if(a==b){chg(dfn[a],dfn[a],v);return;}
    44     while(top[a]!=top[b])if(dep[top[a]]<dep[top[b]])chg(dfn[top[b]],dfn[b],v),b=f[top[b]];
    45         else chg(dfn[top[a]],dfn[a],v),a=f[top[a]];
    46     if(dep[a]>dep[b])chg(dfn[b],dfn[a],v); else chg(dfn[a],dfn[b],v);
    47 }
    48 void query(int a,int b){s.clear();
    49     while(top[a]!=top[b])if(dep[top[a]]<dep[top[b]])ask(dfn[top[b]],dfn[b]),b=f[top[b]];
    50         else ask(dfn[top[a]],dfn[a]),a=f[top[a]];
    51     if(dep[a]>dep[b])ask(dfn[b],dfn[a]); else ask(dfn[a],dfn[b]);
    52 }
    53 int find(int p){return tf[p]==p?p:tf[p]=find(tf[p]);}
    54 int Find(int p){
    55     query(p,p);int x=*s.begin();
    56     if(x!=p)x=Find(x),upd(p,p,x);
    57     return x;
    58 }
    59 int main(){
    60     scanf("%d%d%d",&n,&m,&q);
    61     for(int i=1;i<=m;++i)scanf("%d%d",&E[i].x,&E[i].y),M[E[i].x][E[i].y]=M[E[i].y][E[i].x]=E[i].o=i;
    62     for(int i=1;i<=q;++i)scanf("%s%d%d",o[i],&U[i],&V[i]);
    63     for(int i=1;i<=q;++i)if(o[i][0]=='Z')E[M[U[i]][V[i]]].t=i;
    64     for(int i=1;i<=m;++i)if(!E[i].t)E[i].t=q+1;
    65     sort(E+1,E+1+m);
    66     for(int i=1;i<=n;++i)tf[i]=i;
    67     for(int i=1;i<=m;++i)if(find(E[i].x)!=find(E[i].y))tf[tf[E[i].x]]=tf[E[i].y],te[E[i].o]=1,link(E[i].x,E[i].y),link(E[i].y,E[i].x);
    68     for(int i=1;i<=n;++i)if(find(i)!=find(1)&&i==find(i))link(1,i);
    69     dfs(1,0);DFS(1,1);build(1,1,n);
    70     for(int i=1;i<=m;++i)if(!te[E[i].o]&&E[i].t==q+1){
    71         int F=Find(E[i].x);
    72         query(E[i].x,E[i].y);
    73         rs.clear();swap(s,rs);
    74         for(auto x:rs)upd(Find(x),Find(x),F);
    75     }
    76     for(int i=q;i;--i)if(o[i][0]=='P')ans[i]=Find(U[i])==Find(V[i]);
    77         else if(!te[M[U[i]][V[i]]]){
    78             int F=Find(U[i]);
    79             query(U[i],V[i]);
    80             rs.clear();swap(s,rs);
    81             for(auto x:rs){
    82                 int p=Find(x);
    83                 if(p!=F)upd(p,p,F);
    84             }
    85         }
    86     for(int i=1;i<=q;++i)if(o[i][0]=='P')puts(ans[i]?"Yes":"No");
    87 }
    View Code

    T2:划分序列

    大意:将数列分为k段,使最大段的和最小。$k le n le 50000,|A_i| le 30000$

    这个限制条件看起来真是像二分。

    如果权值都是正的,可以二分。

    如果权值都是负的,可以二分。

    就算不满足这些,还是可以二分。

    二分之后我们看能把这个数列至多/少各能分成多少段,如果k在这个范围内那么就合法。

    感性理解很容易,但是要证明还是有点小恶心。但还是可以证的。

    我们要证明的就是若可以分成$l,r$段就一定可以分成$i(l<i<r)$段。

    对于第一个前缀合法的点一定只能分成一段对吧
    然后对于第二个,要不只能分成一段,要不只能分成两段
    分成一段没有意义,我们假设他只能分成两段
    也就是说sum2>mid
    然后看第三个点
    假设他能分成3段也能分成一段
    那么他一定可以分成两段
    因为如果不能
    则sum3-sum1>mid,sum2>mid
    那么sum3>mid
    不能分成一段
    依次类推
    应该就差不多了趴
    ——By %%mikufun

    类似归纳的方法(其实就是归纳)。没啥毛病。所以就可以心安理得的AC了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 55555
     4 #define inf 1987654321
     5 map<int,int>M;set<int>s;
     6 int n,k,sum[S],ls,c,t[S],T[S],p[S];
     7 void chg(int p,int w){for(;p<=c;p+=p&-p)t[p]=max(t[p],w);}
     8 int ask(int p,int w=-inf){for(;p;p^=p&-p)w=max(w,t[p]);return w;}
     9 void CHG(int p,int w){for(;p<=c;p+=p&-p)T[p]=min(T[p],w);}
    10 int ASK(int p,int w=inf){for(;p;p^=p&-p)w=min(w,T[p]);return w;}
    11 int gt(int x){return c-M[*s.lower_bound(x)];}
    12 int main(){//freopen("1.in","r",stdin);
    13     scanf("%d%d",&n,&k); s.insert(0);s.insert(-inf);s.insert(inf);
    14     for(int i=1;i<=n;++i)scanf("%d",&sum[i]),sum[i]+=sum[i-1],s.insert(sum[i]);
    15     for(auto x:s)M[x]=++c;c++;
    16     for(int i=1;i<=n;++i)p[i]=c-M[sum[i]];
    17     int l=-500000000,r=500000000,md,ans;
    18     while(l<=r){
    19         md=l+r>>1;
    20         for(int i=1;i<=c;++i)t[i]=-inf,T[i]=inf;chg(c-M[0],0);CHG(c-M[0],0);
    21         for(int i=1;i<n;++i)chg(p[i],1+ask(gt(sum[i]-md))),CHG(p[i],1+ASK(gt(sum[i]-md)));
    22         if(ask(gt(sum[n]-md))+1>=k&&k>=1+ASK(gt(sum[n]-md)))r=ans=md,r--;else l=md+1;
    23     }cout<<ans<<endl;
    24 }
    View Code

    T3:生成树求和

    大意:图,求所有生成树的权值和。权值定义为边权做3进制不进位加法的结果。$n le 40,w le 10000$

    都提到进制了,就按位考虑呗。

    每一位只能是0/1/2。我们考虑每条边有几种,然后就变成了《生成树》。

    复杂度$O(n^6 log w)$。有30分。如果写二维拉格朗日插值能少个n卡常后在自家OJ可以AC。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 int E[10][44][44],n,m,ans,o[44][44],oc,mt[44][44],pw[44][44],a[888][888];
     5 void add(int&a,int b){a+=b;if(a>=mod)a-=mod;}
     6 void dec(int&a,int b){add(a,mod-b);}
     7 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     8 int MT(int a=1){
     9     for(int i=1;i<n;++i){
    10         int iv=qp(mt[i][i],mod-2);a=1ll*a*mt[i][i]%mod;for(int j=1;j<n;++j)mt[i][j]=1ll*mt[i][j]*iv%mod;
    11         for(int j=i+1;j<n;++j)for(int k=n-1;k>=i;--k)dec(mt[j][k],1ll*mt[j][i]*mt[i][k]%mod);
    12         a=1ll*a*mt[i][i]%mod;
    13     }return (a+mod)%mod;
    14 }
    15 void Gauss(){
    16     for(int i=1;i<=oc;++i){
    17         if(!a[i][i]){for(int j=i+1;j<=oc;++j)if(a[j][i]){swap(a[i],a[j]);break;}}
    18         int iv=qp(a[i][i],mod-2);for(int j=1;j<=oc+1;++j)a[i][j]=1ll*a[i][j]*iv%mod;
    19         for(int j=1;j<=oc;++j)if(i!=j)for(int k=oc+1;k>=i;--k)dec(a[j][k],1ll*a[j][i]*a[i][k]%mod);
    20     }
    21 }
    22 int main(){
    23     memset(E,0xff,sizeof E);
    24     scanf("%d%d",&n,&m);
    25     for(int a,b,w,i=1;i<=m;++i){scanf("%d%d%d",&a,&b,&w);for(int j=0;j<10;++j)E[j][a][b]=w%3,w/=3;}
    26     for(int i=0;i<n;++i)pw[i][0]=1;
    27     for(int i=0;i<n;++i)for(int j=1;j<=n;++j)pw[i][j]=1ll*pw[i][j-1]*i%mod;
    28     for(int x=0;x<n;++x)for(int y=0;x+y<n;++y)o[x][y]=++oc;
    29     for(int b=0,r=1;b<10;++b,r*=3){
    30         for(int i=1;i<=oc;++i)for(int j=1;j<=oc;++j)a[i][j]=0;
    31         for(int x=0;x<n;++x)for(int y=0;x+y<n;++y){
    32             for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)mt[i][j]=0;
    33             for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
    34                 if(E[b][i][j]==1)add(mt[i][j],x),add(mt[j][i],x),dec(mt[i][i],x),dec(mt[j][j],x);
    35                 else if(E[b][i][j]==2)add(mt[i][j],y),add(mt[j][i],y),dec(mt[i][i],y),dec(mt[j][j],y);
    36                 else if(E[b][i][j]==0)add(mt[i][j],1),add(mt[j][i],1),dec(mt[i][i],1),dec(mt[j][j],1);
    37             a[o[x][y]][oc+1]=MT();
    38         }
    39         for(int x=0;x<n;++x)for(int y=0;x+y<n;++y)for(int i=0;i<n;++i)for(int j=0;i+j<n;++j)a[o[x][y]][o[i][j]]=1ll*pw[x][i]*pw[y][j]%mod;
    40         Gauss();
    41         for(int x=0;x<n;++x)for(int y=0;x+y<n;++y)add(ans,(x+2ll*y)%3*a[o[x][y]][oc+1]%mod*r%mod);//cout<<ans<<endl;
    42     }printf("%d
    ",n&1?ans:mod-ans);
    43 }
    30

    正解挺神奇的。我们最后想知道的并不是每种1边权2边权各多少条的树有多少种,我们想知道的其实是权值和为它的树有多少。

    也即(1边数+2边数×2)的树的数量。我们发现0边权是1,1边权是x,2边权是$x^2$。就解决了问题。

    最后一棵权值和为$a$的树的贡献就是$x^a$。

    权值和的上限是$2n-2$下限$0$。列一个$2n-1$的方程组,代$2n-1$个数进去解出来就行了。

    这样复杂度瓶颈在矩阵树上了,一共$n log w$次。复杂度是$O(n^4 log w)$

    剩下的高斯或者拉格朗日差别不大。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 int E[10][44][44],n,m,ans,mt[44][44],pw[88][88],a[88][88];
     5 void add(int&a,int b){a+=b;if(a>=mod)a-=mod;}
     6 void dec(int&a,int b){add(a,mod-b);}
     7 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     8 int MT(int a=1){
     9     for(int i=1;i<n;++i){
    10         int iv=qp(mt[i][i],mod-2);a=1ll*a*mt[i][i]%mod;for(int j=1;j<n;++j)mt[i][j]=1ll*mt[i][j]*iv%mod;
    11         for(int j=i+1;j<n;++j)for(int k=n-1;k>=i;--k)dec(mt[j][k],1ll*mt[j][i]*mt[i][k]%mod);
    12         a=1ll*a*mt[i][i]%mod;
    13     }return (a+mod)%mod;
    14 }
    15 void Gauss(){
    16     for(int i=1;i<n<<1;++i){
    17         if(!a[i][i]){for(int j=i+1;j<n<<1;++j)if(a[j][i]){swap(a[i],a[j]);break;}}
    18         int iv=qp(a[i][i],mod-2);for(int j=1;j<=n<<1;++j)a[i][j]=1ll*a[i][j]*iv%mod;
    19         for(int j=1;j<n<<1;++j)if(i!=j)for(int k=n<<1;k>=i;--k)dec(a[j][k],1ll*a[j][i]*a[i][k]%mod);
    20     }
    21 }
    22 int main(){
    23     memset(E,0xff,sizeof E);scanf("%d%d",&n,&m);
    24     for(int a,b,w,i=1;i<=m;++i){scanf("%d%d%d",&a,&b,&w);for(int j=0;j<10;++j)E[j][a][b]=w%3,w/=3;}
    25     for(int i=1;i<n<<1;++i)pw[i][0]=1;
    26     for(int i=1;i<n<<1;++i)for(int j=1;j<n<<1;++j)pw[i][j]=1ll*pw[i][j-1]*i%mod;
    27     for(int b=0,r=1;b<10;++b,r*=3){
    28         for(int x=1,y;x<n<<1;++x){y=x*x;
    29             for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)mt[i][j]=0;
    30             for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
    31                 if(E[b][i][j]==1)dec(mt[i][j],x),dec(mt[j][i],x),add(mt[i][i],x),add(mt[j][j],x);
    32                 else if(E[b][i][j]==2)dec(mt[i][j],y),dec(mt[j][i],y),add(mt[i][i],y),add(mt[j][j],y);
    33                 else if(E[b][i][j]==0)dec(mt[i][j],1),dec(mt[j][i],1),add(mt[i][i],1),add(mt[j][j],1);
    34             a[x][n<<1]=MT();
    35         }
    36         for(int x=1;x<n<<1;++x)for(int i=1;i<n<<1;++i)a[x][i]=pw[x][i-1];
    37         Gauss();
    38         for(int x=1;x<n<<1;++x)add(ans,(x-1ll)%3*a[x][n<<1]%mod*r%mod);
    39     }printf("%d
    ",ans);
    40 }
    View Code

    T4:圆圈游戏

    原题《点点的圈圈

  • 相关阅读:
    [LeetCode#91]Decode Ways
    [LeetCode#130]Surrounded Regions
    [LeetCode#84]Largest Rectangle in Histogram
    [LeetCode#179]Largest Number
    [LeetCode#187]Repeated DNA Sequences
    [LeetCode#200]Number of Islands
    [LeetCode#268]Missing Number
    [LeetCode#44]Wildcard Matching
    [LeetCode#128]Longest Consecutive Sequence
    1如何给devexpress的gridview控件绘制全选按钮
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12257630.html
Copyright © 2011-2022 走看看