CSPS模拟86-87

模拟86

T1,烧水,按位统计贡献,利用某种sao操作避免数位dp

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 const int mod=1000000007;
 6 using namespace std;
 7 int n,m;
 8 int dp1[40],sum[40];
 9 int bin[40];
10 inline void get1(int x)
11 {
12     memset(dp1,0,sizeof(dp1));
13     if(x<0)return;
14     for(int i=29;~i;--i)
15     {
16         dp1[i]=(x>>(i+1))+1;
17         if(x&bin[i])dp1[i]=1ll*bin[i]*dp1[i]%mod;
18         else{
19             dp1[i]=1ll*(x>>(i+1))*bin[i]%mod;
20             dp1[i]+=(x&(bin[i]-1));++dp1[i];
21             if(dp1[i]>=mod)dp1[i]-=mod;
22         }
23     }
24 }
25 int main()
26 {
27     for(int i=0;i<=30;++i)bin[i]=1<<i;
28     int T;scanf("%d",&T);
29     while(T--)
30     {
31         scanf("%d%d",&m,&n);
32         memset(sum,0,sizeof(sum));
33         get1(n);
34         for(int i=0;i<=30;++i)sum[i]+=dp1[i];
35         get1(m-1);
36         for(int i=0;i<=30;++i)sum[i]-=dp1[i];
37         int ans=0;const int num=n-m+1;
38         for(int i=0;i<=30;++i)
39         {
40             ans+=2ll*sum[i]%mod*(num-sum[i])%mod*bin[i]%mod;
41             if(ans>=mod)ans-=mod;
42         }
43         ans=((ans%mod)+mod)%mod;
44         cout<<ans<<endl;
45         
46     }
47 }
View Code

T2,博弈,考场上推出了最小为0时的答案,以为能找出规律,连暴力都没打,kuku

正解为用必败状态筛必胜状态来保证复杂度。%%%脸哥压表,处理出不合法状态hash掉,最后在数组里lower_bound即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define re register
 6 using namespace std;
 7 int n,m;
 8 int a[5];
 9 char dp[301][301][301];
10 int main()
11 {
12     for(re short i=0;i<=300;++i)
13     {
14         for(re short j=0;j<=300;++j)
15         {
16             for(re short k=0;k<=300;++k)
17             {
18                 if(dp[i][j][k])continue;
19                 for(re short o=1;o+i<=300;++o)dp[i+o][j][k]=1;
20                 for(re short o=1;o+j<=300;++o)dp[i][j+o][k]=1;
21                 for(re short o=1;o+k<=300;++o)dp[i][j][k+o]=1;
22                 for(re short o=1;o+i<=300&&o+j<=300;++o)dp[i+o][j+o][k]=1;
23                 for(re short o=1;o+i<=300&&o+k<=300;++o)dp[i+o][j][k+o]=1;
24                 for(re short o=1;o+k<=300&&o+j<=300;++o)dp[i][j+o][k+o]=1;
25                 for(re short o=1;o+i<=300&&o+k<=300&&o+j<=300;++o)dp[i+o][j+o][k+o]=1;
26             }
27         }
28     }
29     int T;scanf("%d",&T);
30     while(T--)
31     {
32         scanf("%d%d%d",&a[1],&a[2],&a[3]);
33         if(dp[a[1]][a[2]][a[3]])puts("Yes");
34         else puts("No");
35     }
36 }
View Code

T3,dp,对前缀和取max优化。考场上想出了第三维表示四个状态(顶峰,底端,上升,下降),然而没想到转移。

在最外层枚举区间数,对四种状态用4个变量分别维护最优点转移即可。%%%WWB_star,rnb,milk_feng让我认识到自己的错误

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 30040
 6 using namespace std;
 7 int n,K,ans;
 8 int a[N],sum[N],dp[205][N][5];
 9 const int inf=0x3f3f3f3f;
10 int main()
11 {
12     memset(dp,-0x3f,sizeof(dp));
13     scanf("%d%d",&n,&K);
14     for(int i=1;i<=n;++i)
15         scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
16     int mi=0,ma=0,mi2=0,ma2=0;
17     for(int i=1;i<=n;++i){
18         dp[1][i][2]=sum[i]-mi;
19         dp[1][i][1]=ma-sum[i];
20         dp[1][i][0]=dp[1][i][2];
21         dp[1][i][3]=dp[1][i][1];
22         mi=min(mi,sum[i]);ma=max(ma,sum[i]);
23     }
24     for(int j=2;j<K;++j){
25         mi=ma=mi2=ma2=-inf;
26         for(int i=j-1;i<=n;++i)
27         {
28             dp[j][i][2]=max(dp[j][i][2],ma+2*sum[i]);
29             dp[j][i][1]=max(dp[j][i][1],mi-2*sum[i]);
30             
31             dp[j][i][0]=max(dp[j][i][0],mi2);
32             dp[j][i][3]=max(dp[j][i][3],ma2);
33             mi=max(mi,dp[j-1][i][2]+sum[i]*2);
34             mi=max(mi,dp[j-1][i][0]+sum[i]*2);
35             
36             ma=max(ma,dp[j-1][i][1]-sum[i]*2);
37             ma=max(ma,dp[j-1][i][3]-sum[i]*2);
38             
39             ma2=max(ma2,dp[j-1][i][1]);
40             ma2=max(ma2,dp[j-1][i][3]);
41             
42             mi2=max(mi2,dp[j-1][i][2]);
43             mi2=max(mi2,dp[j-1][i][0]);
44         }
45     }
46     mi=ma=mi2=ma2=-inf;
47     for(int i=K-1;i<=n;++i)
48     {
49         dp[K][i][2]=max(dp[K][i][2],ma+sum[i]);
50         dp[K][i][1]=max(dp[K][i][1],mi-sum[i]);
51         
52         dp[K][i][0]=max(dp[K][i][0],mi2);
53         dp[K][i][3]=max(dp[K][i][3],ma2);
54         
55         mi=max(mi,dp[K-1][i][2]+sum[i]);
56         mi=max(mi,dp[K-1][i][0]+sum[i]);
57         
58         ma=max(ma,dp[K-1][i][1]-sum[i]);
59         ma=max(ma,dp[K-1][i][3]-sum[i]);
60         
61         ma2=max(ma2,dp[K-1][i][1]);
62         ma2=max(ma2,dp[K-1][i][3]);
63         
64         mi2=max(mi2,dp[K-1][i][2]);
65         mi2=max(mi2,dp[K-1][i][0]);
66         
67         ans=max(ans,dp[K][i][2]);
68         ans=max(ans,dp[K][i][1]);
69     }
70     printf("%d
",ans);
71 }
View Code
300 145 120 50 110 220 122 160 130

这个故事告诉我们:rp是个好东西(别败光了)

模拟87,新的开始,勉强苟住位置(抢到Dybala的第八)

T1,(妹子)maze

考场上想了半天才想到是二分答案。然后就疯狂码码码,打了个代码测时长,发现极限数据甚至会达到十几秒,然后疯狂卡常

最后当我手打堆打到一半,发现我的结构体重载运算符重载反了,赶紧改过来,发现还剩1分钟,慌的一比。。。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #define N 105
 10 using namespace std;
 11 const double eps=1e-5;
 12 const int dx[]={1,-1,0,0};
 13 const int dy[]={0,0,1,-1};
 14 int n,m,sx,sy,tx,ty;
 15 bool vst[N][N];
 16 double dis[N][N],s;
 17 int a[N][N];
 18 struct node{
 19     int x;
 20     int y;
 21     double z;
 22     friend bool operator <(const node &a,const node &b)
 23     {return a.z>b.z;}
 24 };
 25 /*
 26 struct QAQ{
 27     node a[100500];
 28     int tot;
 29     inline int size(){return tot;}
 30     inline void clear(){tot=0;}
 31     inline node top(){return a[1];}
 32     inline void pop()
 33     {
 34         a[1]=a[tot++];int i=1,j;
 35         while(1)
 36         {
 37             j=i<<1;
 38             if(j>tot)return;
 39             if(a[j+1]<a[j])
 40         }
 41     }
 42 
 43 }
 44 */
 45 priority_queue<node>q;
 46 inline void init()
 47 {
 48     for(register int i=1;i<=n;++i)
 49         for(register int j=1;j<=m;++j)
 50             dis[i][j]=1000000.0;
 51 }
 52 inline node mknd(int x,int y,double z)
 53 {
 54     node a;a.x=x,a.y=y,a.z=z;return a;
 55 }
 56 inline void dijk(double val)
 57 {
 58     while(q.size())q.pop();init();
 59     dis[sx][sy]=0.0;
 60     q.push(mknd(sx,sy,0.0));
 61     int xx,yy,x,y;double z;
 62     while(q.size())
 63     {
 64         x=q.top().x;y=q.top().y;z=q.top().z;q.pop();
 65         if(z!=dis[x][y])continue;if(x==tx&&y==ty)return;
 66         for(register int i=3;~i;--i)
 67         {
 68             xx=x+dx[i];yy=y+dy[i];
 69             if(a[xx][yy])continue;
 70             if(dx[i])
 71             {
 72                 if(dis[xx][yy]>z+val)
 73                 {
 74                     dis[xx][yy]=z+val;
 75                     q.push(mknd(xx,yy,dis[xx][yy]));
 76                 }
 77             }
 78             else
 79             {
 80                 if(dis[xx][yy]>z+1.0)
 81                 {
 82                     dis[xx][yy]=z+1.0;
 83                     q.push(mknd(xx,yy,dis[xx][yy]));
 84                 }
 85             }
 86         }
 87     }
 88 }
 89 inline void work()
 90 {
 91     double l=0.0,r=s,mid;
 92     while(r-l>3e-4){
 93         mid=(l+r)*0.5;dijk(mid);
 94         if(dis[tx][ty]-s>0.0)r=mid;
 95         else l=mid;
 96         if(fabs(dis[tx][ty]-s)<5e-4){l=mid;break;}
 97 //        printf("%.10lf %.10lf
",l,r);
 98     }
 99     printf("%.3lf
",l);
100 }
101 int main()
102 {
103 //    freopen("da.in","r",stdin);//freopen("my.out","w",stdout);
104     scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty);
105     for(int i=1;i<=n;++i)
106         for(int j=1,x;j<=m;++j)
107             scanf("%d",&x),a[i][j]=x;
108     
109     a[sx][sy]=a[tx][ty]=0;
110     dijk(1.0);if(dis[tx][ty]>100000.0)return 0;
111     for(int i=1;i<=n;++i)a[i][0]=a[i][m+1]=1;
112     for(int i=1;i<=m;++i)a[0][i]=a[n+1][i]=1;
113     scanf("%lf",&s);work();return 0;
114 }
115 /*
116 4 4
117 1 1 4 4
118 0 0 1 1
119 1 0 0 0
120 0 0 1 0
121 0 0 0 0
122 5
123 */
View Code

T2,bird

线段树稍显然,考虑去除重复贡献,用到了一些差分的思想,在左端点加入区间,右点存左点,dp值单点插入时暂且不加当前贡献,扫到右端点再加,保证不重复

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<bitset>
 6 #include<vector>
 7 #include<queue>
 8 #define N 500050
 9 using namespace std;
10 int n,m;
11 vector<int>v[N];
12 int sum[N],dp[N];
13 struct node{
14     int l,r;
15 }q[100050];
16 int A,ans;
17 int ma[N<<2],tag[N<<2];
18 inline void upd(int g){ma[g]=max(ma[g<<1],ma[g<<1|1]);}
19 inline void down(int g)
20 {
21     tag[g<<1]+=tag[g];
22     ma[g<<1]+=tag[g];
23     tag[g<<1|1]+=tag[g];
24     ma[g<<1|1]+=tag[g];
25     tag[g]=0;
26 }
27 inline void add(int g,int l,int r,int x,int y,int v)
28 {
29     if(l>y||r<x)return;
30     if(l>=x&&r<=y){ma[g]+=v;tag[g]+=v;return;}
31     if(tag[g])down(g);
32     const int m=l+r>>1;
33     add(g<<1,l,m,x,y,v);add(g<<1|1,m+1,r,x,y,v);
34     upd(g);
35 }
36 inline int ask(int g,int l,int r,int x,int y)
37 {
38     if(l>y||r<x)return 0;
39     if(l>=x&&r<=y)return ma[g];
40     if(tag[g])down(g);
41     const int m=l+r>>1;
42     const int a1=ask(g<<1,l,m,x,y),a2=ask(g<<1|1,m+1,r,x,y);
43     if(a1>a2)return a1;return a2;
44 }
45 int main()
46 {
47     scanf("%d%d",&n,&m);
48     for(int i=1,l,r;i<=n;++i)
49     {
50         scanf("%d%d",&l,&r);
51         if(r<0)continue;
52         if(l<0)l=0;
53         v[r+1].push_back(l);
54         if(r>A)A=r;
55         ++sum[l];
56     }
57     ++A;int al=0;
58     for(int i=0;i<=A;++i)
59     {
60         al+=sum[i];
61         for(int j=0;j<v[i].size();++j)
62             add(1,0,A,v[i][j],i-1,1),--al;
63         dp[i]=ask(1,0,A,0,i-m);
64         ans=max(ans,dp[i]+al);
65         add(1,0,A,i,i,dp[i]);
66     }
67     cout<<ans<<endl;
68     return 0;
69 }
View Code

T3,%%%脸哥

话说脸哥是不是把推荐和反对放反了啊?

原文地址:https://www.cnblogs.com/loadingkkk/p/11740988.html