[CSP-S模拟测试52]题解
A.平均数
看到第K小,又确定跟平衡树/主席树没有关系,可以把问题转化为有K-1个答案比它小再考虑二分。
二分平均值x,之后将原序列统一减去x。这时序列中区间和<0的区间个数就是原序列中平均值小于x的区间个数。
求个前缀和,那么区间和<0转化成$sum_l > sum_r$,归并排序求逆序对即可。复杂度$O(n\ log^2 \ n)$
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
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;
const double eps=1e-8;
int n,K,num;
double a[N],b[N],sum[N],c[N];
void merge(int l,int r)
{
if(l==r)return ;
int mid=l+r>>1;
merge(l,mid);merge(mid+1,r);
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r)
{
if(sum[i]>sum[j])num+=mid-i+1,c[k]=sum[j],j++;
else c[k]=sum[i],i++;
k++;
}
while(i<=mid)c[k]=sum[i],i++,k++;
while(j<=r)c[k]=sum[j],j++,k++;
for(int i=l;i<=r;i++)sum[i]=c[i];
} bool check(double val)
{
sum[0]=0;num=0;
for(int i=1;i<=n;i++)
a[i]=b[i]-val,sum[i]=sum[i-1]+a[i];
merge(0,n);
return num<K;
} int main()
{
n=read();K=read();
double l=0,r=0;
for(int i=1;i<=n;i++)
b[i]=(double)read();
r=1e9+1.0;
while(r-l>eps)
{
double mid=(l+r)/2.0;
if(check(mid))l=mid;
else r=mid;
}
printf("%.4lf\n",l);
return 0;
}
B.涂色游戏
不会。勉强理解题解之后过掉的。矩阵快速幂一直不能游刃有余地运用到dp优化里,这布星啊。
最裸的矩阵快速幂。
这一行的填色方案只与上一行有关,所以dp。
$dp[i][j]$表示在第i行填了特定j中颜色的方案数。
考虑转移。枚举两行的颜色数再枚举交集即可。
如果上一行有i种下一行有j种交集为k种。
转移条件是$i+j-k<=p\ and\ i+j-k>=q$。
那么就是一个组合数学问题了。
先在上一行的颜色里选出重复部分Cki
再选出这一行交集以外的部分Cj−kp−i
然后的问题就是已知某k种颜色填n个位置,要求每种颜色必须出现。我是dp做的,据说可以容斥。
然后发现每一层的转移系数都相同,那就是简单的矩阵快速幂了。
注意取模。
——DeepinC
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int N=105,M=2005;
int n,p,q;
ll m,C[N][N],A[N][N],b[N][N],res[N],tmp[N][N],tp[N];
void b_mult()
{
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=p;i++)
for(int j=1;j<=p;j++)
for(int k=1;k<=p;k++)
(tmp[i][j]+=b[i][k]*b[k][j]%mod)%=mod;
for(int i=1;i<=p;i++)
for(int j=1;j<=p;j++)
b[i][j]=tmp[i][j];
} void res_mult()
{
memset(tp,0,sizeof(tp));
for(int i=1;i<=p;i++)
for(int j=1;j<=p;j++)
(tp[i]+=res[j]*b[j][i]%mod)%=mod;
for(int i=1;i<=p;i++)
res[i]=tp[i];
}
int main()
{
scanf("%d%lld%d%d",&n,&m,&p,&q);
C[0][0]=A[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=p;j++)
A[i][j]=(A[i-1][j-1]+A[i-1][j])*j%mod;
for(int i=1;i<=p;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++)
(C[i][j]=C[i-1][j-1]+C[i-1][j])%=mod;
}
for(int i=1;i<=p;i++)
for(int j=1;j<=p;j++)
for(int k=0;k<=p;k++)
if(i+j-k<=p&&i+j-k>=q)
(b[i][j]+=C[i][k]*C[p-i][j-k]%mod*A[n][j])%=mod;
for(int i=1;i<=p;i++)
res[i]=A[n][i]*C[p][i]%mod;
m--;
while(m)
{
if(m&1)res_mult();
b_mult();
m>>=1;
}
ll ans=0;
for(int i=1;i<=p;i++)
(ans+=res[i])%=mod;
printf("%lld\n",ans);
return 0;
}
C.序列
先用主席树求第一问。
我们注意到,每次修改后对答案作贡献其实只有范围包括修改点的询问,并且改小了做正贡献,改大了做负贡献。
对于询问建立一棵线段树,下标为询问控制的区间,对每一个结点开一个vector,把所询问的值添加进线段树对应的节点。
将询问按询问值排序,之后按顺序全部更新到线段树中。排序是为了让每个节点的vector内部元素保证有序,确保可以二分查找。
之后对于每次修改,在线段树里查一下改之前该位置的贡献(单点查询,路过每个包含的区间时在它的vector里二分查找),再查一下改之后的,二者做差更新答案,然后在外部数组里更改即可。
复杂度$O(n\ log^2 \ n)$。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
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;
typedef long long ll;
int n,m,Q,a[N];
struct ques
{
int l,r,val;
friend bool operator < (ques x,ques y)
{
return x.val<y.val;
}
}q[N];
int ls[N*40],rs[N*40],size[N*40],type,root[N];
ll ans;
void update(int &k,int l,int r,int old,int val)
{
k=++type;
ls[k]=ls[old];
rs[k]=rs[old];
size[k]=size[old]+1;
if(l==r)return ;
int mid=l+r>>1;
if(val<=mid)update(ls[k],l,mid,ls[old],val);
else update(rs[k],mid+1,r,rs[old],val);
}
int query(int k,int l,int r,int val)
{
if(l==r)return size[k];
int mid=l+r>>1,res=0;
if(val<=mid)return size[rs[k]]+query(ls[k],l,mid,val);
else return query(rs[k],mid+1,r,val);
}
vector<int> w[N<<2];
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
void add(int k,int l,int r,int L,int R,int val)
{
if(L<=l&&R>=r)
{
w[k].push_back(val);
return ;
}
int mid=l+r>>1;
if(L<=mid)add(ls(k),l,mid,L,R,val);
if(R>mid)add(rs(k),mid+1,r,L,R,val);
}
int ask(int k,int l,int r,int pos,int val)
{
int res=upper_bound(w[k].begin(),w[k].end(),val)-w[k].begin()-1;
if(l==r)return res;
int mid=l+r>>1;
if(pos<=mid)res+=ask(ls(k),l,mid,pos,val);
else res+=ask(rs(k),mid+1,r,pos,val);
return res;
}
int main()
{
n=read();m=read();Q=read();
for(int i=1;i<=n;i++)
a[i]=read(),update(root[i],1,n,root[i-1],a[i]);
for(int i=1;i<=m;i++)
{
q[i].l=read(),q[i].r=read(),q[i].val=read();
int res1=query(root[q[i].r],1,n,q[i].val),res2=query(root[q[i].l-1],1,n,q[i].val);
ans+=res1-res2;
}
sort(q+1,q+m+1);
for(int i=1;i<=m;i++)
add(1,1,n,q[i].l,q[i].r,q[i].val);
printf("%lld\n",ans);
while(Q--)
{
int p=read()^ans,v=read()^ans;
int res1=ask(1,1,n,p,a[p]),res2=ask(1,1,n,p,v);
ans+=res2-res1;
a[p]=v;
printf("%lld\n",ans);
}
return 0;
}
[CSP-S模拟测试52]题解的更多相关文章
- csp-s模拟测试52平均数,序列题解
题面:https://www.cnblogs.com/Juve/articles/11602244.html 平均数: 第k个平均数不好求,我们考虑二分,转化成平均数小于x的有几个 虑把序列中的每个数 ...
- CSP-S 模拟测试94题解
T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...
- CSP-S模拟测试 88 题解
T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...
- CSP-S 模拟测试92 题解
话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...
- CSP-S 模拟测试57题解
人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...
- CSP-S 模拟测试 51 题解
考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...
- CSP-S 模拟测试 45 题解
由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...
- [CSP-S模拟测试97]题解
A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...
- [CSP-S模拟测试96]题解
以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘 ...
随机推荐
- PHP基于PDO实现的SQLite操作类
<?php // sqlite分页类 class SqliteDB{ public function __construct(){ // 初始化数据库,并且连接数据库 数据库配置 $this-& ...
- 22 October in 614
Contest A. defile struct 自定义排序.按照题意抽象成模型模拟就可以了. 自定义排序核心代码: struct node { int x, id; } d[1000003]; bo ...
- Instagram几个queryhash
page_query_hash 42323d64886122307be10013ad2dcc44comment_query_hash 33ba35852cb50da46f5b5e889df7d159f ...
- Java JsonPath grab InvalidPathException in code, you must be catching Java 7's java.nio.file.InvalidPathException instead of JsonPath's com.jayway.jsonpath.InvalidPathExceptio
I am using JsonPath and am able to parse my data and get the values when the path provided is correc ...
- AGC037C Numbers on a Circle
题目大意 给你一个序列a和序列b 每次操作是a[i]+=a[i-1]+a[i+1] 问a经过最少几次操作可以得到b 分析 用堆维护a 每次取出最大的 撤销操作直到不能撤销 将新数放入堆 不断维护即可 ...
- Map-Amap:目录
ylbtech-Map-Amap:目录 1. 高德地图返回顶部 1. https://www.amap.com/ 2. 2. 高德地图App返回顶部 1. http://www.autonavi.c ...
- Windows 08R2_AD图文详解
目录 目录 软件环境 Active Directory域服务 AD的应用 创建ADDS域 使用Windows窗口来创建ADDS域控制器 使用Powershell来创建ADDS域控制器 检查ADDC域控 ...
- Java数据访问对象模式
数据访问对象模式或DAO模式用于将低级数据访问API或操作与高级业务服务分离. 以下是数据访问对象模式的参与者. 数据访问对象接口 - 此接口定义要对模型对象执行的标准操作. 数据访问对象具体类 - ...
- Pikachu漏洞练习平台实验——CSRF(三)
概述 CSRF 是 Cross Site Request Forgery 的 简称,中文名为跨域请求伪造 在CSRF的攻击场景中,攻击者会伪造一个请求(一般是一个链接) 然后欺骗目标用户进行点击,用户 ...
- web自动化,selenium 无法清空输入框默认值继续输入
有的页面输入框自带默认值,想要修改里面的内容时,先使用clear()再send_keys(),这种方式无法清除只会在默认值后面追加内容,不是我想要的结果 解决方法: 方法一: 先双击,后直接send_ ...