zoukankan      html  css  js  c++  java
  • CSP-S 模拟53 题解

    题解:

    T1 u:

    一看到修改这么多,但询问其实只有一个不难想到差分,但是他这个形状可以说很不规则,于是我们想到分别维护竖着的和斜着的差分,然后最后合并即可。

    考场上瞎调了一波系数莫名AC,其实是维护差分的差分。

    考试时发现对拍暴力输不出来东西时,慌的不行,对拍的数据范围一定要搞对。

     1 //weihu xiezhede chafen?
     2 //对于每个满足 x ∈ [r, r +l), y ∈ [c, x−r +c]
     3 //的元素 (x, y),将权值增加 s。
     4 #include<bits/stdc++.h>
     5 using namespace std;
     6 #define int long long
     7 #define sc(x) printf("%lld
    ",x)
     8 const int N=1e3+10;
     9 int cf[N][N],cf1[N][N],n,q,a[N][N];
    10 signed main(){
    11     //freopen("data.in","r",stdin);
    12     //freopen("my.out","w",stdout);
    13     scanf("%lld%lld",&n,&q);
    14     if(!q){puts("0");return 0;}
    15     for(int i=1;i<=q;++i){
    16         int r,c,l,s;
    17         scanf("%lld%lld%lld%lld",&r,&c,&l,&s);
    18         cf[r][c]+=s;
    19         cf1[r][c+1]+=s;
    20         if(r+l<=n) cf[r+l][c]-=s;
    21         if(r+l<=n&&c+l+1<=n) cf1[r+l][c+l+1]-=s;
    22     }
    23     for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cf[i][j]+=cf[i-1][j];
    24     for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cf1[i][j]+=cf1[i-1][j-1];
    25     int ans=0;
    26     for(int i=1;i<=n;++i){
    27         for(int j=1;j<=n;++j){
    28             cf[i][j]-=cf1[i][j];
    29         }
    30     }
    31 //    ans=cf[1][1];
    32     for(int i=1;i<=n;++i){
    33         for(int j=1;j<=n;++j){
    34             cf[i][j]+=cf[i][j-1];
    35             //cout<<cf[i][j]<<" ";
    36             ans^=cf[i][j];
    37         }
    38         //cout<<endl;
    39     }
    40     sc(ans);
    41 }
    u

    T2 v:

    考场上想状压,但是发现数据范围稍大,可能过不了,然后也没什么思路。

    正解 记忆化搜索+hash_map,其实是和裸状压一样的,但是加了记忆化加速,比较难搞的一点就是如何把删了一个球后的状态用二进制表示出来,有点绕。

    还有就是,hash_map不能仅仅记录状态,还要记录当前所剩的球数,因为000110和000110对于状态来说是一样的,但是前面的黑球数是不一定的,这样保证状态唯一。所以hash_map有点难搞,%%%DeepinC重载中括号取地址hash_map,因为自己是实在是不会hash_map,所以就没脸得照着DeepinC神的hash_map打了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=35;
     4 #define signed long long
     5 const int M=3e7+10;
     6 char s[N];
     7 int n,k,a[N];
     8 struct hash_map{//hash_map shizhaozhe DeepinC dedade zhendebuhui hash_map
     9     int first[30000017],nex[M],to[M],tot;short l[M],len;
    10     double val[M];
    11     double &operator[] (const register int st){
    12         signed f=st*1ll*len%30000017;
    13         for(register int i=first[f];i;i=nex[i]) if(to[i]==st&&l[i]==len) return val[i];
    14         to[++tot]=st,nex[tot]=first[f],first[f]=tot,l[tot]=len; val[tot]=-1;return val[tot];
    15     }
    16 }mp;
    17 inline double max(const register double  a,const register double b){
    18     return a>b?a:b;
    19 }
    20 
    21 double dfs(const register int l,const register int st){//cout<<l<<" "<<st<<endl;
    22     if(l==n-k) return 0.0;
    23     mp.len=l;//meicichongxinfuzhi,yinwei zhuangtaihechangdushiduiyingde
    24     if(mp[st]>-0.1) return mp[st];
    25     mp[st]=0;
    26     short sta[N],jk=l+1,kh=(l>>1)+1;
    27     for(register int i=1;i^jk;++i) sta[i]=(st>>i-1)&1;
    28 //    reverse(sta+1,sta+l+1);
    29 //    for(int i=1;i<=l;++i) cout<<sta[i]<<" ";cout<<endl;
    30 
    31     for(register int  i=1;i^kh;++i){
    32         short h=l-i+1;
    33         int state1=st>>l-i+1<<l-i|st&(1<<l-i)-1,state2=st>>l-h+1<<l-h|st&(1<<l-h)-1;
    34 //        cout<<st<<" "<<l<<" "<<i<<endl;
    35 //        cout<<state1<<" "<<state2<<endl;
    36         double ans1=dfs(l-1,state1)+sta[h],ans2=dfs(l-1,state2)+sta[i];
    37         mp.len=l;mp[st]+=(2.0*max(ans1,ans2))/(1.0*l);
    38     }
    39     if(l&1){
    40         int i=kh;
    41         int state=st>>l-i+1<<l-i|st&(1<<l-i)-1;
    42         double ans=dfs(l-1,state)+sta[i];
    43         mp.len=l;mp[st]+=ans/(1.0*l);
    44     }
    45     return mp[st];
    46 }
    47 
    48 int main(){
    49     scanf("%d%d",&n,&k);
    50     scanf("%s",s+1);
    51     int st=0;
    52     for(register signed i=1;i<=n;++i) a[i]=(s[i]=='W');
    53     for(register signed i=1;i<=n;++i) st=st<<1|a[i];
    54     printf("%.7lf",dfs(n,st));
    55 }
    v

    T3:

    考场上以为是个贪心,就和虎那题差不多,实际上是个思路非常好的dp

    首先贪心地考虑,每个边顶多被覆盖一次,因为被覆盖两次以上完全可以从这条便断开,那么会使答案更优。

    我们设$dp[i][0/1]$表示以点i为根的子树否/是向上伸,因为他的两个答案是同时更新的,所以。

    然后考虑对于i的儿子y,我们设两个二元组w1,w2,w1表示向上伸,w2表示不向上伸。

    那么我们考虑转移$w1=min(w1+dp[y][0],w2+dp[y][1])$,$w2=min(w1+dp[y][1],w2+dp[y][0])$

    那么我们在来考虑怎么用w1,w2进行转移。

    如果他这条边不翻转,那么能不反转就不反转,所以$dp[x][1]=(INF,INF)$,$dp[x][0]=min(w2,(w1.first+1,w1.second))$

    如果必须反转的话,那么同理$dp[x][0]=(INF,INF)$,$dp[x][1]=min((w1.first,w1.second+1),(w2.first+1,w2.second+1))$

    最后答案就是$dp[1][0].first/2$和$dp[1][0].second$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=3e5+10,INF=1e9+10;
     4 int first[N],nex[N<<1],to[N<<1],edge[N<<1],tot;
     5 void add(int a,int b,int c){
     6     to[++tot]=b,nex[tot]=first[a],first[a]=tot,edge[tot]=c;
     7 }
     8 pair<int ,int> min(pair<int ,int> a,pair<int ,int > b){
     9     return a<b?a:b;
    10 }
    11 pair<int ,int> add(pair<int,int> a,pair<int ,int> b){
    12     return make_pair(a.first+b.first,a.second+b.second);
    13 }
    14 pair<int ,int> dp[N][2];//0 not up 1 up
    15 void dfs(int x,int fa,int ed){
    16     pair<int ,int > p,q;
    17     p=make_pair(INF,INF);//up
    18     q=make_pair(0,0);//not up
    19     pair<int ,int> tmp1,tmp2;//p q;
    20     for(int i=first[x];i;i=nex[i]){
    21         int y=to[i];
    22         if(y==fa) continue;
    23         dfs(y,x,edge[i]);
    24         tmp1=min(add(p,dp[y][0]),add(q,dp[y][1]));
    25         tmp2=min(add(q,dp[y][0]),add(p,dp[y][1]));
    26         p=make_pair(tmp1.first,tmp1.second);
    27         q=make_pair(tmp2.first,tmp2.second);
    28     }
    29     if(ed==1||ed==2){//bi fan
    30         dp[x][1]=min(make_pair(p.first,p.second+1),make_pair(q.first+1,q.second+1));
    31     }else dp[x][1]=make_pair(INF,INF);
    32     if(ed==0||ed==2){//bu fan
    33         dp[x][0]=min(q,make_pair(p.first+1,p.second));
    34     }else dp[x][0]=make_pair(INF,INF);
    35 }
    36 
    37 int main(){
    38     int n;
    39     scanf("%d",&n);
    40     for(int i=1;i<n;++i){
    41         int a,b,c,d;
    42         scanf("%d%d%d%d",&a,&b,&c,&d);
    43         int opt;
    44         if(d==2) opt=2;
    45         else if(c^d) opt=1;
    46         else opt=0;
    47         add(a,b,opt);
    48         add(b,a,opt);
    49     }
    50     dfs(1,0,2);
    51     printf("%d %d",dp[1][0].first>>1,dp[1][0].second);
    52 }
    View Code
  • 相关阅读:
    从温设计模式
    php pdf转图片
    PHP 微服务集群搭建
    死磕nginx系列--nginx 限流配置
    分别
    一生悲哀
    三十男人的思考
    test markdown
    linux 系统内核空间与用户空间通信的实现与分析<转>
    ue4 SNew补遗
  • 原文地址:https://www.cnblogs.com/leom10/p/11604116.html
Copyright © 2011-2022 走看看