模拟测试52,53反思

这两次考试都挂了不少分,也学到了很多东西。

52 T1 常数写大正解T成暴力

   T2 数组越界70->50又由于我的智障操作最后一秒50->20

53 T2 逆推打成正推100->21

   T3 暴力56pts,错解57pts,机智的我交了暴力,还把数组开小了57->43。

1.虽然不同算法的理论复杂度是一样的,但是常数真的很重要!map常数很大!

2.在不确定自己打的是对的时候,不要在最后时刻交代码。

3.期望逆着推,其实不是期望,对于最优决策来说,要么枚举所有决策,

  判断优劣,要么先逆着算出所有的情况的答案,寻找决策(记忆化搜索)

4.在代码过不了对拍的时候,一定要认真对待暴力。

5.矩阵快速幂某种程度上是说:x[i][j]表示j转移到i的系数。

6.记得测一下极限数据。

T1 平均数

sb题(谁正解T成暴力谁sb)

 

 1 #include<cstdio>
 2 #define N 100005
 3 using namespace std;
 4 int a[N],n,k;
 5 long long sum[N],ans;
 6 double tmp[N],q[N];
 7 inline int read()
 8 {
 9     int x=0;char c=getchar();
10     while(c<'0'||c>'9')c=getchar();
11     while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
12     return x;
13 }
14 void solve(int l,int r)
15 {
16     if(l==r)return ;
17     int mid=l+r>>1;
18     solve(l,mid),solve(mid+1,r);
19     int pl=l,pr=mid+1,tot=l-1;
20     while(pl<=mid&&pr<=r)
21     {
22         if(tmp[pr]<=tmp[pl]) ans+=(mid-pl+1),q[++tot]=tmp[pr++];
23         else q[++tot]=tmp[pl++];
24     }
25     while(pl<=mid) q[++tot]=tmp[pl],pl++;
26     while(pr<=r) q[++tot]=tmp[pr],pr++;
27     for(register int i=l;i<=r;i++) tmp[i]=q[i];
28     return ;
29 }
30 inline bool check(double x)
31 {
32     tmp[1]=0;ans=0;
33     for(register int i=1;i<=n;++i)
34         tmp[i+1]=sum[i]-i*x;
35     solve(1,n+1);
36     return ans<k;
37 }
38 inline double _min(double a,double b){return a<b?a:b;}
39 inline double _max(double a,double b){return a>b?a:b;}
40 int main()
41 {
42     double l=0x7f7f7f7f,r=0;
43     n=read(),k=read();
44     for(register int i=1;i<=n;++i)a[i]=read(),l=_min(l,1.0*a[i]),r=_max(r,1.0*a[i]),sum[i]=sum[i-1]+a[i];
45     while(r-l>1e-5)
46     {
47         double mid=(l+r)/2;//printf("%lf",mid);
48         if(check(mid))l=mid;
49         else r=mid;
50     }
51     printf("%.4lf\n",l);
52     return 0;
53 }
View Code

 

T2 涂色游戏

我打的很麻烦。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define int long long
 4 using namespace std;
 5 const int mod=998244353;
 6 int C[105][105],dp[105],g[105][105],fx[105][105][105],ed[105],n,m,p,q;
 7 struct M{
 8     int x[105][105];
 9     friend M operator * (const M a,const M b)
10     {
11         M c; memset(c.x,0,sizeof c.x);
12         for(int i=1;i<=p;i++)
13             for(int j=1;j<=p;j++)
14                 for(int k=1;k<=p;k++)
15                     (c.x[i][j]+=a.x[i][k]*b.x[k][j]%mod)%=mod;
16         return c;
17     }
18     void clear()
19     {
20         for(int i=1;i<=p;i++)x[i][i]=1;
21     }
22     void out(){for(int i=1;i<=p;i++,puts(""))for(int j=1;j<=p;j++)cout<<x[i][j]<<' ';}
23 }ans,now;
24 inline void qpower(int b)
25 {
26     ans.clear();//ans.out();
27     for(;b;b>>=1,now=now*now) if(b&1)ans=ans*now;
28     return ;
29 }
30 signed main()
31 {
32     scanf("%lld%lld%lld%lld",&n,&m,&p,&q); C[1][0]=C[1][1]=C[0][0]=g[1][1]=1;
33     for(int i=2;i<=100;C[i++][0]=1)
34         for(int j=1;j<=i;j++)
35             C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod,
36             g[j][i]=(g[j-1][i-1]*j%mod+g[j][i-1]*j%mod)%mod;
37     for(int i=0;i<=p;i++)
38         for(int j=0;j<=p;j++)
39             for(int k=0;k<=j;k++)
40                 fx[i][j][k]=(fx[i][j][k-1]+C[i][k]*C[p-i][j-k]%mod)%mod;
41     for(int i=1;i<=p;i++)dp[i]=C[p][i]*g[i][n]%mod;
42     for(int j=1;j<=p;j++)
43         for(int k=q-j;k<=p;k++)
44         {
45             if(k<1) continue;
46             if(k<q)now.x[j][k]=(C[p][j]-fx[p-k][j][q-k-1]+mod)%mod*g[j][n]%mod;
47             else now.x[j][k]=C[p][j]*g[j][n]%mod;
48         }
49     qpower(m-1);
50     for(int i=1;i<=p;i++)
51         for(int j=1;j<=p;j++)
52             (ed[i]+=ans.x[i][j]*dp[j]%mod)%=mod;
53     int ans=0;
54     for(int j=1;j<=p;j++) (ans+=ed[j])%=mod;
55     printf("%lld\n",ans);
56 }
View Code

T3 序列

开一棵主席树维护询问区间,把每个区间拆成两个前缀询问,第一次询问统计每个点的贡献,后面再直接弄即可。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<vector>
 4 #define N 100005
 5 using namespace std;
 6 vector<int>cs[2][N];
 7 int rt[2][N],a[N];
 8 long long ans;
 9 inline int read()
10 {
11     int x=0;char c=getchar();
12     while(c<'0'||c>'9')c=getchar();
13     while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
14     return x;
15 }
16 struct Segtree{
17     int ls[N<<6],rs[N<<6],s[N<<6],tot;
18     void insert(int &k,int l,int r,int pos,int pre)
19     {
20         if(!k)k=++tot;
21         if(l==r)
22         {
23             if(!s[k])s[k]=s[pre]+1;
24             else s[k]++;
25             return ;
26         }
27         int mid=l+r>>1;
28         if(pos<=mid) 
29         {
30             if(!rs[k])rs[k]=rs[pre];
31             if(ls[k]==ls[pre])ls[k]=++tot;
32             insert(ls[k],l,mid,pos,ls[pre]);
33         }
34         else 
35         {    
36             if(!ls[k])ls[k]=ls[pre]; 
37             if(rs[k]==rs[pre])rs[k]=++tot;
38             insert(rs[k],mid+1,r,pos,rs[pre]);
39         }
40         s[k]=s[ls[k]]+s[rs[k]];
41     }
42     int query(int k,int l,int r,int ll,int rr)
43     {
44         if(l>=ll&&r<=rr) {return s[k];}
45         int mid=l+r>>1;
46         return (ll<=mid?query(ls[k],l,mid,ll,rr):0)+(rr>mid?query(rs[k],mid+1,r,ll,rr):0);
47     }
48 }T;
49 int main()
50 {
51     int n=read(),m=read(),q=read();
52     for(int i=1;i<=n;i++)a[i]=read();
53     for(int i=1;i<=m;i++)
54     {
55         int l=read(),r=read(),x=read();
56         cs[0][x].push_back(l-1),cs[1][x].push_back(r);
57     }
58     for(int i=1;i<=n;i++)
59     {
60         if(!cs[0][i].size()) rt[0][i]=rt[0][i-1],rt[1][i]=rt[1][i-1];
61         for(int j=0;j<cs[0][i].size();j++) T.insert(rt[0][i],0,n,cs[0][i][j],rt[0][i-1]);
62         for(int j=0;j<cs[1][i].size();j++) T.insert(rt[1][i],0,n,cs[1][i][j],rt[1][i-1]);
63     }
64     for(int i=1;i<=n;i++)
65         ans+=T.query(rt[1][a[i]],0,n,i,n)-T.query(rt[0][a[i]],0,n,i,n);
66     printf("%lld\n",ans);
67     while(q--)
68     {
69         int p=read()^ans,v=read()^ans;
70         if(v<a[p])
71             ans-=T.query(rt[1][a[p]],0,n,p,n),ans+=T.query(rt[1][v],0,n,p,n),
72             ans+=T.query(rt[0][a[p]],0,n,p,n),ans-=T.query(rt[0][v],0,n,p,n);
73         else if(v^a[p])
74             ans+=T.query(rt[1][v],0,n,p,n),ans-=T.query(rt[1][a[p]],0,n,p,n),
75             ans-=T.query(rt[0][v],0,n,p,n),ans+=T.query(rt[0][a[p]],0,n,p,n);
76         a[p]=v;
77         printf("%lld\n",ans);
78     }
79     return 0;
80 }
View Code

Lockey大神打的比较简单的打法:维护对每个位置的询问,差分+主席树维护前缀。

具体来说:对于一个询问Q(l,r,x),先在l处把x询问++,在r+1处x询问--。

一个一个插入主席树,再询问前缀,就能得到某点的询问,值得借鉴。

还有$O(nlogn^2)$的线段树加vector,不再多说。

T1 u

差分题,只有2*n条斜线,直接差分维护。

 1 #include<cstdio>
 2 #define N 2005
 3 #define int long long
 4 using namespace std;
 5 int cf[N][N],gt[N][N],tot,fir[N][N],n;
 6 inline int _min(int a,int b){return a<b?a:b;}
 7 inline int read()
 8 {
 9     int x=0;char c=getchar();
10     while(c>'9'||c<'0')c=getchar();
11     while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
12     return x;
13 }
14 void Get(int x,int y)
15 {        
16     fir[x][y]=cf[x][y];
17     if(x+1>0&&y+1<=n)
18     {
19         cf[x+1][y+1]+=cf[x][y];
20         Get(x+1,y+1);
21     }
22 }
23 signed main()
24 {
25     n=read();
26     int q=read(),ans=0;
27     while(q--)
28     {
29         int r=read(),c=read(),l=read(),s=read();
30         gt[r][c]+=s;
31         gt[_min(r+l,n+1)][c]-=s;
32         cf[r][c+1]-=s;
33         cf[_min(r+l,n+1)][_min(c+l+1,n+1)]+=s;
34     }
35     for(int i=1;i<=n;i++)Get(1,i);
36     for(int i=2;i<=n;i++)Get(i,1);
37     for(int i=1;i<=n;i++)
38         for(int j=1;j<=n;j++)
39         {
40             gt[j][i]+=gt[j-1][i];
41             fir[j][i]+=gt[j][i];
42         }
43     for(int i=1;i<=n;i++)
44         for(int j=1;j<=n;j++)
45         {
46             fir[i][j]+=fir[i][j-1];
47             ans^=fir[i][j];
48         }
49     printf("%lld\n",ans);
50     return 0;
51 }
View Code

T2 v

典型状压题,记忆化一下AC,状态数我并不会证。

 1 #include<cstdio>
 2 #define mod 2333333
 3 using namespace std;
 4 struct Hushmap{
 5     int cnt,head[2400000],to[mod+1],nxt[mod+1];
 6     double id[mod+1];
 7     void insert(long long x,double p)
 8     {
 9         int k=x%mod;
10         to[++cnt]=x,nxt[cnt]=head[k],id[cnt]=p,head[k]=cnt;
11     }
12     double find(long long x)
13     {
14         int k=x%mod;
15         for(int i=head[k];i;i=nxt[i]) if(to[i]==x) return id[i];
16         return -1;
17     }
18 }H[31];
19 int n,k;
20 char s[105];
21 inline int gank(int x,int w)
22 {
23     int tmp=x&((1<<w)-1);
24     x>>=(w+1);x<<=w;tmp|=x;
25     return tmp;
26 }
27 inline double _max(double a,double b)
28 {
29     return a>b?a:b;
30 }
31 double dfs(int now,int st)
32 {
33     if(now==k+1) return 0;
34     double jc=H[now].find(st);
35     if(jc>=0)return jc;
36     double tmp=0;
37     for(int i=1;i<=n-now+1;i++)
38     {
39         int ot=n-now+2-i;
40         double a,b;
41         a=dfs(now+1,gank(st,i-1))+((st>>i-1)&1);
42         b=dfs(now+1,gank(st,ot-1))+((st>>ot-1)&1);
43         tmp+=_max(a,b)/(n-now+1);
44     }
45     H[now].insert(st,tmp);
46     return tmp;
47 }
48 int main()
49 {
50     double ans=0;int st=0;
51     scanf("%d%d",&n,&k);
52     scanf("%s",s+1);
53     for(int i=1;i<=n;i++)
54     {
55         int tmp=0;
56         if(s[i]=='W')tmp=1;
57         else tmp=0;
58         st|=(tmp<<i-1);
59     }
60     printf("%.8lf\n",dfs(1,st));
61     return 0;
62 }
View Code

T3 w

暴力/乱搞可以搞到80分(数据水)

正解是二元组DP,由于路径条数不好维护,维护奇数点,合并子树,分情况讨论即可。

 1 #include<bits/stdc++.h>
 2 #define N 200005
 3 #define INF 200001
 4 #define mp make_pair
 5 #define fir first
 6 #define sec second
 7 #define P pair<int,int>
 8 using namespace std;
 9 int to[N<<1],nxt[N<<1],head[N],cnt=1,col[N<<1],toc[N<<1],ans=0;
10 pair<int,int>dp[N][2];
11 inline void Add(int u,int v,int fr,int ty){to[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt,col[cnt]=fr,toc[cnt]=ty;}
12 inline int read()
13 {
14     int x=0;char c=getchar();
15     while(c>'9'||c<'0')c=getchar();
16     while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
17     return x;
18 }
19 inline int _max(int a,int b){return a>b?a:b;}
20 inline int _min(int a,int b){return a<b?a:b;}
21 inline P add(P a,P b)
22 {
23     return mp(a.fir+b.fir,a.sec+b.sec);
24 }
25 void dfs(int x,int pre)
26 {
27     P w1=mp(INF,INF),w2=mp(0,0); 
28     for(int i=head[x];i;i=nxt[i])
29     {
30         if(i==(pre^1))continue;
31         int y=to[i];
32         dfs(y,i);
33         P tmp1=w1,tmp2=w2;
34         w1=min(add(tmp1,dp[y][0]),add(tmp2,dp[y][1]));
35         w2=min(add(tmp1,dp[y][1]),add(tmp2,dp[y][0]));
36     }
37     if(col[pre]==(toc[pre]^1)) dp[x][0]=mp(INF,INF),dp[x][1]=min(add(w1,mp(0,1)),add(w2,mp(1,1)));
38     else if(col[pre]==toc[pre]) dp[x][1]=mp(INF,INF),dp[x][0]=min(add(w1,mp(1,0)),w2);
39     else dp[x][1]=min(add(w1,mp(0,1)),add(w2,mp(1,1))),dp[x][0]=min(add(w1,mp(1,0)),w2);
40     return ;
41 }
42 int main()
43 {
44     int n=read();
45     for(int i=1,a,b,c,d;i<n;i++)
46     {
47         a=read(),b=read(),c=read()+2,d=read()+2,Add(a,b,c,d),Add(b,a,c,d);
48         if(c==(d^1))ans++;
49     }
50     dfs(1,0);
51     printf("%d %d\n",dp[1][0].fir/2,dp[1][0].sec);
52 }
View Code
posted on 2019-09-28 12:14  _kx  阅读(184)  评论(0编辑  收藏  举报