题面:

模拟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序列,二叉搜索树,走路题解的更多相关文章

  1. 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历

    二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历   二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则 ...

  2. 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历

    二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值:若它的右子树不空,则右子树上所有结点的值均大于它的根 ...

  3. [CSP-S模拟测试]:二叉搜索树(DP+贪心)

    题目传送门(内部题99) 输入格式 第一行一个整数$n$,第二行$n$个整数$x_1\sim x_n$. 输出格式 一行一个整数表示答案. 样例 样例输入: 58 2 1 4 3 样例输出: 数据范围 ...

  4. 【遍历二叉树】07恢复二叉搜索树【Recover Binary Search Tree】

    开一个指针数组,中序遍历这个二叉搜索树,将节点的指针依次保存在数组里, 然后寻找两处逆序的位置, 中序便利里BST得到的是升序序列 ++++++++++++++++++++++++++++++++++ ...

  5. 【剑指offer】二叉搜索树转双向链表,C++实现

    原创博文,转载请注明出处! # 题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 二叉树节点的定义 struct TreeNod ...

  6. 剑指Offer面试题:22.二叉搜索树的后序遍历序列

    一.题目:二叉搜索树的后序遍历序列 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 例如在下面 ...

  7. Interview----判断整数序列是否是二叉搜索树的后序遍历结果

    题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果:   ...

  8. (剑指Offer)面试题24:二叉搜索树的后序遍历序列

    题目: 输入一个整数数组,判断该数组是不是某个二叉搜索树的后序遍历的结果,如果是则返回true,否则返回false. 假设输入的数组的任意两个数字都互不相同. 思路: 根据二叉搜索树的后序遍历特点,很 ...

  9. P140、面试题24:二叉搜索树的后序遍历序列

    题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 测试用例: 1)功能测试(输入的后序遍历的序列 ...

随机推荐

  1. idea springboot 打包 war

    1.pom文件中将项目改为   war

  2. Android四大组件之Service浅见

    Service 是Android四大组件之一,可以在不显示界面的情况下在后台运行.还有一个作用是通过AIDL来实现进程间通信. Service的启动方式 Service的启动方式有两种,startSe ...

  3. 因kernel too old 而 centos6.8 升级内核

    因为docker运行centos 的时候,报错了,错误为kernel too old .我看了一下是因为os的内核不行了,需要升级下内核. 查看默认版本: uname -r 忘记截图了,内核大概是2. ...

  4. [转]WPF的依赖属性是怎么节约内存的

    WPF升级了CLR的属性系统,加入了依赖属性和附加属性.依赖属性的使用有很多好处,其中有两点是我认为最为亮眼的: 1)节省内存的开销; 2)属性值可以通过Binding依赖于其它对象上,这就使得我的数 ...

  5. hadoop创建目录文件失败

    mkdir: Cannot create directory /file. Name node is in safe mode.   刚刚在hadoop想创建一个目录的时候,发现报错了 具体信息如下: ...

  6. C++11的闭包(lambda、function、bind)

    c++11开始支持闭包,闭包:与函数A调用函数B相比较,闭包中函数A调用函数B,可以不通过函数A给函数B传递函数参数,而使函数B可以访问函数A的上下文环境才可见(函数A可直接访问到)的变量:比如: 函 ...

  7. R语言 运算符

    R语言运算符 运算符是一个符号,通知编译器执行特定的数学或逻辑操作. R语言具有丰富的内置运算符,并提供以下类型的运算符. 运算符的类型 R语言中拥有如下几种运算符类型: 算术运算符 关系运算符 逻辑 ...

  8. [HL] 7.5 集训总结

    对于某唤做赛区难度的题,我只能是内流满面..拿到题,A神题不可做,B,神题不可做,C,神题不可做...最后yy了一个A的算法...只得了20 TAT.C题骗分似乎有50 ..B题本来想骗分..然后/ ...

  9. 排列+函数映射——hdu6038好题

    /* 引理:[0,n-1]的排列,i向a[i]连边,那么每个数必定在一个环中 所以数组a可以分割成一些环,数组b也可以分割成一些环 先讨论a的一个环 a[a1]=a2 a[a2]=a3 a[a3]=a ...

  10. 树上莫比乌斯反演+分层图并查集——cf990G

    /* 树上莫比乌斯反演 求树上 满足 d|gcd(au,av) gcd(au,av)的对数f(d) 如何求: 建立200000层新图,即对于每个数建立一个新图 在加边时,给gcd(au,av)的约数层 ...