[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=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
int n,q;
ll dif1[N][N],dif2[N][N];
int main()
{
    //freopen("dt.in","r",stdin);
    //freopen("my.out","w",stdout);
    n=read();q=read();
    while(q--)
    {
        int r=read(),c=read(),l=read(),val=read();
        dif1[r][c]+=val;dif1[r+l][c]-=val;
        dif2[r][c+1]-=val;dif2[r+l][c+l+1]+=val;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            dif2[i][j]+=dif2[i-1][j-1],dif1[i][j]+=dif1[i-1][j];
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            dif1[i][j]+=dif1[i][j-1]+dif2[i][j],ans^=dif1[i][j];
    }
    cout<<ans<<endl;
    return 0;
}

B.v

二进制状压一下当前场上剩余球的状态,记搜即可。记忆化状态需要手写Hash表,直接map会T飞。

另外,在本题中形如00110和0110的状态是不同的,为了区分我们可以给Hash表多加一个长度的参数,每次查询或插入时先调到相应的长度再操作。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int H=2e7+5;
struct hash_map
{
    int head[19260820],nxt[H],to[H],tot;
    short L[H],len;
    double val[H];
    double &operator [] (int key)
    {
        int x=1LL*key*len%19260817;
        for(int i=head[x];i;i=nxt[i])
            if(to[i]==key&&L[i]==len)return val[i];
        nxt[++tot]=head[x];
        head[x]=tot;
        to[tot]=key;
        L[tot]=len;
        return val[tot]=-1;
    }
}h;
const int N=35;
int n,K;
char s[N];
int erase(int st,int pos)
{
    return st>>pos<<pos-1|st&(1<<pos-1)-1;
}
double dfs(int pos,int st)
{
    if(n-K==pos)return 0;
    h.len=pos;int sst=st;
    if(h[st]>=0)return h[st];
    h[st]=0;
    int rez[N];
    for(int i=1;i<=pos;i++,sst>>=1)
        rez[i]=sst&1;
    for(int i=1;i<=(pos>>1);i++)
    {
        int j=pos-i+1;
        int s1=erase(st,j),s2=erase(st,i);
        double res1=dfs(pos-1,s1)+rez[j],res2=dfs(pos-1,s2)+rez[i];
        h.len=pos;h[st]+=2.0/pos*max(res1,res2);
    }
    if(pos&1)
    {
        int i=(pos>>1)+1,s1=erase(st,pos-i+1);
        double res=dfs(pos-1,s1)+rez[i];
        h.len=pos;h[st]+=1.0/pos*res;
    }
    return h[st];
}

int main()
{
    scanf("%d%d%s",&n,&K,s+1);
    int now=0;
    for(int i=1;i<=n;i++)
    {
        now<<=1;
        if(s[i]==‘W‘)now|=1;
    }
    printf("%.7lf\n",dfs(n,now));
    return 0;
}

C.w

神仙dp。如果把反转一条路径看作增加这样的一条路径,那么最终增加的路径数就等于奇点个数/2。

(由于这道题太神了所以我还是咕掉好了)

#include<cstdio>
#include<iostream>
#include<cstring>
#define pa pair<int,int>
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
const int N=1e5+5,inf=0x3f3f3f3f;
int n;
int to[N<<1],head[N],nxt[N<<1],w[N<<1],tot;
pa dp[N][2];
pa pls(pa x,pa y)
{
    return make_pair(x.first+y.first,x.second+y.second);
}
void add(int x,int y,int z)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
    w[tot]=z;
}
void dfs(int x,int f,int e)
{
    pa a=make_pair(0,0),b=make_pair(inf,inf),c,d;
    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        if(y==f)continue;
        dfs(y,x,w[i]);
        c=min(pls(a,dp[y][0]),pls(b,dp[y][1]));
        d=min(pls(a,dp[y][1]),pls(b,dp[y][0]));
        a=c;b=d;
    }
    if(e==1)dp[x][0]=make_pair(inf,inf);
    else dp[x][0]=min(a,make_pair(b.first+1,b.second));
    if(e==0)dp[x][1]=make_pair(inf,inf);
    else dp[x][1]=min(make_pair(a.first+1,a.second+1),make_pair(b.first,b.second+1));
}

int main()
{
    n=read();
    for(int i=1;i<n;i++)
    {
        int x=read(),y=read(),col=read(),aim=read(),z;
        if(aim==2)z=aim;
        else z=col^aim;
        add(x,y,z);add(y,x,z);
    }
    dfs(1,1,0);
    cout<<(dp[1][0].first>>1)<<‘ ‘<<dp[1][0].second<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Rorschach-XR/p/11610775.html

时间: 2024-08-30 15:37:31

[CSP-S模拟测试53]题解的相关文章

CSP-S 模拟测试57题解

人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T2 巨神兵: 大神题,一看数据范围这么小,我们考虑状压,最傻逼的暴力思路是压边,但是这显然不行.正解是压点,设$f[s]$为当前选定点集状态为$s$的方案数. 我们考虑转移,当前选定的点集肯定是可以通过边和没有连过来的点相连构成新的方案.所以转移所以我们考虑枚举补集的子集$k$,设$cnt$为s与k

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

以后题解还是单独放吧. A.Divisors 根号筛求所有数的因子,扫一遍去重统计即可. #include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<map> using namespace std; const int N=205; int a[N],m,n; map<int,int> bu; vector<int> re

CSP-S模拟测试69 题解

一如既往的垃圾,又回到了那个场场垫底的自己,明明考场上都想到正解了,但是就是拿不到分,可能是互奶把rp用光了吧以后一定加强训练代码能力. T1: 考场上一直yy矩阵快速幂,虽然自己矩阵快速幂一点都不会还是硬着头皮yy,发现不可做之后并没有及时转化思路,但其实自己预处理的数组就是正解. 切记:不仅矩阵快速幂是log的,普通快速幂也是2333 然后这题其实很水啊,我们设$dp[i][j]$为前$i$列放$j$个棋子的方案数,然后枚举最后一列放多少个棋子就好了. 转移方程为$dp[i][j]=\sum

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

以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘数里的2去掉就好了. 坑点2:1e18炸long long $\rightarrow$ 慢速乘即可 #include<cstdio> #include<iostream> #include<cstring> #include<vector> using name

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

A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼知道为什么要等于这个) 然后再定义当前局面的期望函数为每个人期望函数之和. 然后你会发现每次猜拳后局面期望函数变化量都是1 那么期望步数其实就是终止局面期望函数值-初始局面期望函数值 $ans=2^{n-1}-1-\sum (2^{cnt[x]}-1)$ #include<bits/stdc++.h

模拟测试53

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

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

这个起名方式居然还有后续?! 为什么起名不是连续的?! T1想了半天,搞出来了,结果数组开小[其实是没注意范围].T2概率期望直接跳,后来翻回来写发现自己整个理解错了期望的含义[何].T3错误想到赛道修建结果来了个错误贪心. 关于T2破罐子破摔输出k居然骗了二十分这件事…… T1u: 一开始各种想偏,维护哪种值是奇数或偶数个,考虑每次操作影响哪些值变化…这些全都跑出来了. 大概过了一个世纪那么长,突然想着能不能直接优化操作的过程啊,然后对暴力进行钻研,终于开始想到差分. 然后觉着nq的复杂度过不

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

回去要补一下命运石之门了…… A.嘟嘟噜 给定报数次数的约瑟夫,递推式为$ans=(ans+m)\% i$. 考虑优化,中间很多次$+m$后是不用取模的,这种情况就可以把加法变乘法了.问题在于如何找到下一次需要取模的位置. 解不等式$ans+km \ge i+k$即可,需要处理一下边界. 据说可以证明复杂度是$O(m \log n)$的,但我不是很会. //考场代码 稍丑 #include<bits/stdc++.h> using namespace std; typedef long lon

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

A.Median 这题的数据生成方式并没有什么规律,所以可以认为是随机数据. 维护一个桶,表示当前K长区间里的值域情况. 并且用变量记录中位数值域上的左侧有多少个数,当区间调整时一并调整桶和这个变量即可. 由于是随机数据,所以每次的调整幅度并不会很大,近似于常数. 复杂度$O(n)$. #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespa