2019.9.27 csp-s模拟测试53 反思总结

这个起名方式居然还有后续?!

为什么起名不是连续的?!

T1想了半天,搞出来了,结果数组开小【其实是没注意范围】。T2概率期望直接跳,后来翻回来写发现自己整个理解错了期望的含义【何】。T3错误想到赛道修建结果来了个错误贪心。

关于T2破罐子破摔输出k居然骗了二十分这件事……

T1u:

一开始各种想偏,维护哪种值是奇数或偶数个,考虑每次操作影响哪些值变化…这些全都跑出来了。

大概过了一个世纪那么长,突然想着能不能直接优化操作的过程啊,然后对暴力进行钻研,终于开始想到差分。

然后觉着nq的复杂度过不去,开始对差分进行瞎搞。终于又过了一个世纪那么久,发现差分数组也是可以传递转移的……

两个世纪过去了,没有然后了。

#include<iostream>
#include<cstdio>
using namespace std;
int n,q;
long long ans,f[2010][2010],H[2010][2010],L[2010][2010],sum;
int main()
{
    scanf("%d%d",&n,&q);
    if(!q){
        printf("0\n");
        return 0;
    }
    else if(n<=300){
        for(int i=1,r,c,l,s;i<=q;i++){
            scanf("%d%d%d%d",&r,&c,&l,&s);
            for(int j=r;j<r+l;j++){
                for(int k=c;k<=j-r+c;k++){
                    f[j][k]+=s;
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                ans^=f[i][j];
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
    else if(q<=2000){
        for(int i=1,r,c,l,s;i<=q;i++){
            scanf("%d%d%d%d",&r,&c,&l,&s);
            for(int j=r;j<r+l;j++){
                H[j][c]+=s;
                H[j][j-r+c+1]-=s;
            }
        }
        for(int i=1;i<=n;i++){
            sum=0;
            for(int j=1;j<=n;j++){
                sum+=H[i][j];
                ans^=sum;
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
    else{
        for(int i=1,r,c,l,s;i<=q;i++){
            scanf("%d%d%d%d",&r,&c,&l,&s);
            H[r][c]+=s;
            L[r][c+1]-=s;
            H[r+l][c]-=s;
            L[r+l][c+l+1]+=s;
        }
        for(int i=1;i<=n;i++){
            sum=0;
            for(int j=1;j<=n;j++){
                H[i][j]+=H[i-1][j];
                L[i][j]+=L[i-1][j-1];
                sum+=H[i][j]+L[i][j];
                ans^=sum;
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
}

T2v:

整个儿弄错了期望这东西,一言难尽。

题目中的最优策略,指的是在以某一概率选到某一个位置的时候,选择拿前面的球或者拿后面的球的其中一种决策产生的贡献,累计上这个球是不是白球的贡献,取最大值。

所以dfs,枚举选到的是哪个位置,累积贡献,除以可选到多少种位置,就是这一状态的期望。

因为搜索到的状态会有很多重复,考虑记忆化搜索。但是表示某一状态的数字可能很大,数组下标无法表述。那么对于数组表示得出来的,就用数组存。其它更大的用map映射解决。

不同长度的状态可能存在数值上相同的情况,例如010和0010。解决方法是在这一长度的再靠前一位打上一个1的标记,例如010->1010,0010->10010,这样表示不同的状态。

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
int n,k;
char s[31];
long long fir;
double ans,num[(1<<25)];
map<long long,double>m;
double dfs(long long x,int k,int lon){
    if(!k)return 0;
    if(lon<=25&&num[x]!=-1.0)return num[x];
    else if(m.find(x)!=m.end())return m[x];
    double f=0,f1=0,val1,val2;
    long long x1,x2;
    for(int i=1;i<=lon/2;i++){
        val1=(x>>(lon-i-1))&1,val2=(x>>(i-1))&1;
        f1=0;
        x1=(x>>1)&(~((1<<(lon-i-1))-1))|(x&((1<<(lon-i-1))-1));
        x2=(x>>1)&(~((1<<(i-1))-1))|(x&((1<<(i-1))-1));
        f1=dfs(x1,k-1,lon-1)+val1;
        f1=max(f1,dfs(x2,k-1,lon-1)+val2);
        f+=f1*(i==lon-i?1.0:2.0);
    }
    f/=(double)(lon-1);
    if(lon<=25)num[x]=f;
    else m[x]=f;
    return f;
}
int main(){
    scanf("%d%d",&n,&k);
    scanf("%s",s+1);
    for(int i=0;i<=(1<<25);i++)num[i]=-1.0;
    fir=1;
    for(int i=1;i<=n;i++){
        fir=(fir<<1)+(s[i]==‘W‘);
    }
    ans=dfs(fir,k,n+1);
    printf("%.10lf",ans);
    return 0;
}

T3w:

错误贪心:强行认为每个节点由子节点传上来的路径若有偶数条就自行解决是最优的,奇数条就看当前节点连出去的边目标是不是2,然后无脑传上去。

错误性显而易见……有可能强行传上去的这条会打乱父节点本来可以完整自行配对的组合,给父节点增加一条路径,然后不得不再次穿上去,又增加了长度……还不如在当前节点自行了断。

正解是树形DP。发现最后的总路径数是整棵树路径中的奇度数点数/2。对于每个点,记录它传一条边上去或者不传的时候dp[x][1],dp[x][0],包含子树的最少奇度数点数以及在此基础上的最小总路径长。

一棵一棵子树进行转移。设两个用来统计子树们的最优答案的二元组w1,w2。w1的含义是子树们传了一条边上来,w2是不传让它们两两解决。对于每棵子树y,w1=min(w2+dp[y][1],w1+dp[y][0]),w2=min(w1+dp[y][1],w2+dp[y][0])。比较大小的时候都优先比较奇度数点数c1,再比较路径长度c2。

然后根据当前节点上面这条边的状态和目标状态计算dpx。显然一条边如果已经是目标状态,那么始终不走一定是更优的。如果这条边已经是目标状态,让dp[x][1]=inf。使w1的c1++,w2不变,表示若有边传上来就多一个奇度数点作为收尾,或者没有边传上来就不变,然后dp[x][0]在w1和w2中选择更优的。如果这条边不是目标状态,就让dp[x][0]=inf。w1.c2++。w2.c1++,w2.c2++,表示这个节点作为一个新的开头使奇度数节点增加。依然让dp[x][1]在w1和w2中选择更优的。如果这条边的目标状态是2,就两种情况非inf的部分都做一遍。

#include<iostream>
#include<cstdio>
using namespace std;
const int inf=214748364;
int f[100010][2],opt[100010],goal[100010];
struct node{
    int c1,c2;
}dp[100010][2],tool;
int n,tot,ver[200010],head[100010],edge[200010],edge1[200010],Next[200010];
void add(int x,int y,int z,int w){
    ver[++tot]=y;
    Next[tot]=head[x];
    head[x]=tot;
    edge[tot]=z;
    edge1[tot]=w;
}
node work(node a,node b,node c,node d){
    node e;
    if(a.c1+b.c1<c.c1+d.c1){
        e.c1=a.c1+b.c1;
        e.c2=a.c2+b.c2;
    }
    else if(a.c1+b.c1==c.c1+d.c1){
        if(a.c2+b.c2<c.c2+d.c2){
            e.c1=a.c1+b.c1;
            e.c2=a.c2+b.c2;
        }
        else{
            e.c1=c.c1+d.c1;
            e.c2=c.c2+d.c2;
        }
    }
    else{
        e.c1=c.c1+d.c1;
        e.c2=c.c2+d.c2;
    }
    return e;
}
void dfs(int x,int fa){
    node w1,w2;
    w1.c1=w1.c2=inf;
    w2.c1=w2.c2=0;
    for(int i=head[x];i;i=Next[i]){
        int y=ver[i];
        if(y==fa)continue;
        opt[y]=edge[i];
        goal[y]=edge1[i];
        dfs(y,x);
        node w11=w1;
        w1=work(dp[y][0],w1,dp[y][1],w2);
        w2=work(dp[y][1],w11,dp[y][0],w2);
    }
    if(goal[x]==2){
        w2.c1++;
        w1.c2++;
        w2.c2++;
        dp[x][1]=work(w1,tool,w2,tool);
        w2.c1--;
        w1.c2--;
        w2.c2--;
        w1.c1++;
        dp[x][0]=work(w1,tool,w2,tool);
    }
    else{
        if(opt[x]!=goal[x]){
            dp[x][0].c1=inf,dp[x][0].c2=inf;
            w2.c1++;
            w1.c2++;
            w2.c2++;
            dp[x][1]=work(w1,tool,w2,tool);
        }
        else{
            dp[x][1].c1=inf,dp[x][1].c2=inf;
            w1.c1++;
            dp[x][0]=work(w1,tool,w2,tool);
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1,x,y,z,w;i<n;i++){
        scanf("%d%d%d%d",&x,&y,&z,&w);
        add(x,y,z,w),add(y,x,z,w);
    }
    dfs(1,0);
    printf("%d %d\n",dp[1][0].c1/2,dp[1][0].c2);
    return 0;
}

结果拖到这会儿才写完。

祝祖国母亲生日快乐。

原文地址:https://www.cnblogs.com/chloris/p/11614594.html

时间: 2024-07-31 10:36:04

2019.9.27 csp-s模拟测试53 反思总结的相关文章

2019.9.28 csp-s模拟测试54 反思总结

咕咕咕的冲动如此强烈x T1x: 看完题目想了想,感觉把gcd不为1的强行放在一组,看作一个连通块,最后考虑连通块之间的组合方式就可以了. 然后维护这个连通块可以写并查集可以连边跑dfs怎么着都行… 然而我在处理数字分解质因数这里T掉了,原因是一个很显然的优化写法我基本没怎么写过.线性筛的时候记录每个数是被哪个质数标记过的,分解一个数的时候直接处理记录下来的质数就可以. #include<iostream> #include<cstdio> #include<cmath>

2019.10.22 csp-s模拟测试82 反思总结

算了 我在干什么orz T2: #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1e5+10,p=1500007,mod=998244353; int n,len,cnt1=1,cnt2=1,lens; char s[2*N],c[2*N]; int tree1[2*N][27],tree2[2*N][27]; unsigned long lon

2019.10.30 csp-s模拟测试94 反思总结

头一次做图巨的模拟题OWO 自从上一次听图巨讲课然后骗了小礼物以后一直对图巨印象挺好的233 T1: 对于XY取对数=Y*log(x) 对于Y!取对数=log(1*2*3*...*Y)=log1+log2+log3+...+logY 因为数字大小不超过1e5,直接累加最后比较就可以了 #include<iostream> #include<cstdio> #include<cmath> using namespace std; int t,x,y; double a,b

2019.9.19 csp-s模拟测试47 反思总结

思路接近正解?都想到了?这都是借口呀. 没有用的,往前走吧. T1:Emotional Flutter 我的做法和题解不太一样,我把s放在最后考虑了. 因为出发以后步幅是一样的,所以每一个黑条可以ban掉一段出发点.把黑条的左右边界%k存成区间,每个黑条可以存一个或者两个区间[跨越k这个边界].然后像以前写区间覆盖的贪心一样按左端点排序,看看有没有长至少为s的空余. 代码: #include<iostream> #include<cstdio> #include<cstrin

2019.9.20 csp-s模拟测试48 反思总结

头疼,不说废话了,祝大家rp++. T1: 暴力枚举,n3. 枚举两个串开始匹配的位置,每一次尽量修改. #include<iostream> #include<cstdio> using namespace std; int n,k,cnt,num,ans; char a[310],b[310]; int main() { scanf("%d%d",&n,&k); scanf("%s",a+1); scanf("%

模拟测试53

T1: 我们不仅可以维护差分,还可以维护差分的差分,两次前缀和即可. 注意区间可能延伸到矩形之外,特判一下即可. 时间复杂度$O(n^2)$ T2: 可以状压DP或记忆化搜索. 记录状态为当前哪些小球被拿走了,然后逆推转移就行了. 但是小球的颜色只有两种,我们可以将状态定义重设为剩下小球的颜色. 这样大大减少了状态数. 时间复杂度$O(nk2^{C_n^k})$ T3: DP神题. 根据贪心思想,一条边至多会被覆盖一次. 因为如果一条边被两条路径覆盖,从这条边两侧截开这两条路径一定能使答案更优.

[CSP-S模拟测试53]题解

A.u 只涉及到区间修改可以考虑差分,然而如果每一行都差分复杂度还是过高.我们发现差分标记也是连续的(一行横着的一行斜着的),所以可以维护两个 差分的差分,扫两遍统计即可. #include<cstdio> #include<iostream> #include<cstring> using namespace std; typedef long long ll; const int N=2005; int read() { int x=0,f=1;char ch=ge

2019.9.26 csp-s模拟测试52 反思总结

刚刚写了一个小时的博客没了,浏览器自动刷新. 一!个!小!时! 鼠标键盘电脑哪个都不能摔,气死我了. 垃圾选手T1T2没思路,T3倒是想出来得比较早,靠T3撑着分数. 数据结构学傻选手,属实垃圾. T1平均数: 一个序列的所有数如果减去x,那么平均数也会减去x.可以二分这个x,统计序列里平均数小于0的序列的个数,含义为原序列平均数小于x的序列的个数.最后统计值小于k且最接近k的x就是所求答案. 序列的平均数小于0,那么序列的和也一定小于0.表现在前缀和上即为一个区间的sumr<suml-1,转化

2019.9.29 csp-s模拟测试55 反思总结

不咕咕咕是一种美德[大雾] 头一次体会到爆肝写题解??? 这次考试我们没赶上,是后来掐着时间每个人自己考的.我最后的分数能拿到152…熟悉的一题AC两题爆炸. 强烈吐槽出题人起名走心 T1联: 发现每一次加入一个区间的操作,只有区间的l或者r+1有可能成为答案.那么考虑能不能用这两个点代表一整个区间,维护全局最靠左的0在什么地方. 把每个操作的l和r+1都存下来,离散化,建一棵线段树.每一次区间操作都针对线段树上的a[l]-a[r+1]-1这部分(a[x]为x离散化以后的排序,即线段树里的位置)