csps模拟93序列,二叉搜索树,走路题解
题面:
模拟93考得并不理想,二维偏序没看出来,然而看出来了也不会打
序列:
对a,b数列求前缀和,那么题意转化为了满足$suma[i]>=suma[j]$且$sumb[i]>=sumb[j]$的最大$i-j+1$值
那么就是二维偏序,那么按a排序,把b塞到树状数组里
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<ctime>
#define int long long
using namespace std;
const int MAXN=5e5+;
int n,ans=,sta[MAXN],top=;
int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){
if(ch=='-') f=-;
ch=getchar();
}
while(ch>=''&&ch<=''){
x=(x<<)+(x<<)+ch-'';
ch=getchar();
}
return x*f;
}
struct node{
int a,b,id;
friend bool operator < (node p,node q){
return p.a==q.a?p.b<q.b:p.a<q.a;
}
}val[MAXN];
int lowbit(int x){
return x&-x;
}
int c[MAXN];
void update(int pos,int val){
for(int i=pos;i<=top;i+=lowbit(i)){
c[i]=min(c[i],val);
}
}
int query(int pos){
int res=0x3f3f3f3f3f3f3f3f;
for(int i=pos;i>;i-=lowbit(i)){
res=min(res,c[i]);
}
return res;
}
signed main(){
n=read();
for(int i=;i<=n;++i){
val[i].a=read();
val[i].a+=val[i-].a;
val[i].id=i;
}
for(int i=;i<=n;++i){
val[i].b=read();
val[i].b+=val[i-].b;
sta[++top]=val[i].b;
}
sort(val+,val+n+);
sort(sta+,sta+top+);
top=unique(sta+,sta+top+)-sta-;
for(int i=;i<=n;++i)
val[i].b=lower_bound(sta+,sta+top+,val[i].b)-sta;
memset(c,0x3f,sizeof(c));
for(int i=;i<=n;++i){
int res=query(val[i].b);
ans=max(ans,val[i].id-res);
update(val[i].b,val[i].id);
}
printf("%lld\n",ans);
return ;
}
二叉搜索树:
区间dp,设f[i,j]表示考虑区间[i,j]的贡献,则f[i,j]=min(f[i,k-1]+f[k+1,j]+a[i,j])
然后发现k有决策单调性,所以我们记录一个dp数组,dp[i,j]表示f[i,j]是由那一个k转移而来,然后对于每一个i,j,枚举k的范围就变成了dp[i+1,j]到dp[i,j-1]
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define int long long
using namespace std;
const int MAXN=;
int n,ans=,sum[MAXN],f[MAXN][MAXN],dp[MAXN][MAXN];
struct node{
int x,id;
friend bool operator < (node p,node q){
return p.x==q.x?p.id>q.id:p.x>q.x;
}
}a[MAXN];
int min(int p,int q){
return p<q?p:q;
}
signed main(){
memset(f,0x3f,sizeof(f));
scanf("%lld",&n);
for(int i=;i<=n;++i){
scanf("%lld",&a[i].x);
a[i].id=i;
sum[i]=sum[i-]+a[i].x;
f[i][i]=a[i].x;
dp[i][i]=i;
}
for(int i=;i<=n+;++i){
for(int j=;j<i;++j) f[i][j]=;
}
for(int l=;l<=n;++l){
for(int i=;i+l-<=n;++i){
int j=i+l-;
for(int k=dp[i][j-];k<=dp[i+][j];++k){
if(f[i][j]>=f[i][k-]+f[k+][j]+sum[j]-sum[i-]){
f[i][j]=f[i][k-]+f[k+][j]+sum[j]-sum[i-];
dp[i][j]=k;
}
}
}
}
printf("%lld\n",f[][n]);
return ;
}
走路:分治消元
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
const int MAXM=1e5+,mod=;
int n,m,du[],cnt[][],inv[MAXM],a[][],ans[];
int q_pow(int a,int b,int p){
int res=;
while(b){
if(b&) res=res*a%p;
a=a*a%p;
b>>=;
}
return res;
}
void solve(int l,int r){
if(l==r){
ans[l]=(a[][n+]+mod)%mod;
return ;
}
int t[][];
for(int i=;i<=n;++i){
for(int j=;j<=n+;++j)
t[i][j]=a[i][j];
}
int mid=(l+r)>>;
for(int x=mid+;x<=r;++x){
int invv=q_pow(a[x][x],mod-,mod);
for(int i=;i<=n+;++i) (a[x][i]*=invv)%=mod;
for(int i=;i<=n;++i){
if(i==x) continue;
invv=a[i][x];
for(int j=l;j<=r;++j){
a[i][j]=(a[i][j]-a[x][j]*invv+mod)%mod;
}
a[i][n+]=(a[i][n+]-a[x][n+]*invv+mod)%mod;
}
}
solve(l,mid);
for(int i=;i<=n;++i){
for(int j=;j<=n+;++j)
a[i][j]=t[i][j];
}
for(int x=l;x<=mid;++x){
int invv=q_pow(a[x][x],mod-,mod);
for(int i=;i<=n+;++i) (a[x][i]*=invv)%=mod;
for(int i=;i<=n;++i){
if(i==x) continue;
invv=a[i][x];
for(int j=l;j<=r;++j){
a[i][j]=(a[i][j]-a[x][j]*invv%mod+mod)%mod;
}
a[i][n+]=(a[i][n+]-a[x][n+]*invv%mod+mod)%mod;
}
}
solve(mid+,r);
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=,u,v;i<=m;++i){
scanf("%lld%lld",&u,&v);
++du[u],++cnt[u][v];
}
for(int i=;i<=m;++i) inv[i]=q_pow(i,mod-,mod);
for(int i=;i<=n;++i){
for(int j=;j<=n;++j){
a[i][j]=cnt[i][j]*q_pow(du[i],mod-,mod)%mod;
}
a[i][n+]=-;
--a[i][i];
}
solve(,n);
for(int i=;i<=n;++i) printf("%lld\n",ans[i]);
return ;
}
csps模拟93序列,二叉搜索树,走路题解的更多相关文章
- 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历
二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历 二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则 ...
- 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历
二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值:若它的右子树不空,则右子树上所有结点的值均大于它的根 ...
- [CSP-S模拟测试]:二叉搜索树(DP+贪心)
题目传送门(内部题99) 输入格式 第一行一个整数$n$,第二行$n$个整数$x_1\sim x_n$. 输出格式 一行一个整数表示答案. 样例 样例输入: 58 2 1 4 3 样例输出: 数据范围 ...
- 【遍历二叉树】07恢复二叉搜索树【Recover Binary Search Tree】
开一个指针数组,中序遍历这个二叉搜索树,将节点的指针依次保存在数组里, 然后寻找两处逆序的位置, 中序便利里BST得到的是升序序列 ++++++++++++++++++++++++++++++++++ ...
- 【剑指offer】二叉搜索树转双向链表,C++实现
原创博文,转载请注明出处! # 题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 二叉树节点的定义 struct TreeNod ...
- 剑指Offer面试题:22.二叉搜索树的后序遍历序列
一.题目:二叉搜索树的后序遍历序列 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 例如在下面 ...
- Interview----判断整数序列是否是二叉搜索树的后序遍历结果
题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: ...
- (剑指Offer)面试题24:二叉搜索树的后序遍历序列
题目: 输入一个整数数组,判断该数组是不是某个二叉搜索树的后序遍历的结果,如果是则返回true,否则返回false. 假设输入的数组的任意两个数字都互不相同. 思路: 根据二叉搜索树的后序遍历特点,很 ...
- P140、面试题24:二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 测试用例: 1)功能测试(输入的后序遍历的序列 ...
随机推荐
- linux每日命令(2):ps命令
ps命令真是我比较常用的命令了,只是也没咋仔细研究过,最大的用处就是写代码的时候,起了多进程,就会占用多个进程,如果程序异常了,进程确没有kill掉,那么再启动程序就会报错 正常起项目 如果进程被占用 ...
- box-shadow单侧投影,双侧投影,不规则图案投影
底部投影box-shadow: 0 5px 4px -4px black; 底部右侧投影 3px 3px 6px -3px black 两侧投影 box-shadow: 7px 0 7px -7px ...
- whatis - 在 whatis 数据库里查找完整的单词
总览 (SYNOPSIS) whatis keyword ... 描述 (DESCRIPTION) whatis 命令在一些特定的包含系统命令的简短描述的数据库文件里查找关键字, 然后把结果送到标准输 ...
- selenium提取不了标签文本
1.举个例子:selenium使用driver.find_element_by_xpath().text 提取不到标签文本?? 如果我们提取的元素文本为空时,而不是我们想要的文本时,这时可能就是因为你 ...
- Spring使用Redis
1.引入依赖 <dependency> <groupId>org.springframework.data</groupId> <artifactId> ...
- delphi常见的错误
******************************* * 编 译 错 误 信 息 * ******************************* ';' not allowed befo ...
- bzoj1004题解
[题意分析] 给N个元素染色,可以在定置换群的作用下互相转化的染色方案算相同的,问本质不同的染色方案数. [解题思路] 引理:Burnside定理 设集合S=[1,n]∩N,记等价类数为L,给定S上的 ...
- kafka-manager监控工具的安装和使用
kafka-manager监控工具的使用 第一步:对kafkamanager进行下载并编译 此步骤略:可参照成功与否不详,https://www.jianshu.com/p/174b6eb10d9d ...
- ArcGIS中QueryTask,FindTask,IndentifyTask 之间的区别
1:QueryTask是一个进行空间和属性查询的功能类,它可以在某个地图服务的某个子图层内进行查询,顺便需要提一下的是,QueryTask进行查询的地图服务并 不必项加载到Map中进行显示.Query ...
- sql语句中----删除表数据drop、truncate和delete的用法(转)
转载于:http://www.cr173.com/html/40708_1.html 说到删除表数据的关键字,大家记得最多的可能就是delete了 然而我们做数据库开发,读取数据库数据.对另外的两兄弟 ...