emmmmmmmm
jzoj 6090 圆
https://jzoj.net/senior/#main/show/6090
dp。
能分成三个上升子序列的话,说明最长下降子序列不能超过3.。。。
考虑把数从小到大依次加入序列中
那么我们目前要加入的那个数一定是序列中最大的
发现如果在某个位置右边下降子序列长度为3,那么这个位置左边一定不能加数
那我们就想办法维护这种位置
但是不是很好搞。
主要是要找到dp转移出现区别的临界点
我们看看右边可以加入的部分
考虑这样一个位置x:他的右边一直到序列结束都是单增,左边的第一个位置比他大
其实就是右端点的极长下降连续序列的最后一个位置
在这个位置两边插入新数产生的效果并不一样:
- 1.如果插左边,那么新数,x-1处和x处的三个数构成长度为3的下降子序列,那么新插入的位置左边以后都不可以再插
- 2.如果插右边,那么新数切断了原来的极长下降连续序列,即x变为新插入的位置
这样看来dp就可以写了,只需要维护极长下降连续序列的长度,和x左边还可以插入新数区间的长度
用前缀和优化就好
当然你高兴的话还可以打表。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int MAXN=505;
int n,mod,o;
LL f[2][MAXN][MAXN],s1[2][MAXN][MAXN],s2[2][MAXN][MAXN],ans;
void add(LL &a,LL b){
a+=b;
if(a>=mod) a-=mod;
}
int main(){
freopen("yuan.in","r",stdin);
freopen("yuan.out","w",stdout);
cin>>n>>mod;
f[o][1][0]=s2[o][1][1]=1;
for(int i=2;i<=n;i++){
o^=1;
for(int j=0;j<=i;j++)for(int k=0;k<=i;k++) f[o][j][k]=s1[o][j][k]=s2[o][j][k]=0;
for(int j=1;j<=i;j++)for(int k=0;j+k<=i;k++){
if(!k&&j!=i) continue;
add(f[o][j][k],f[o^1][j-1][k]);
add(f[o][j][k],s1[o^1][j][k]);
add(f[o][j][k],s2[o^1][j+k-1][j]);
add(s1[o][j][k],f[o][j][k]);
add(s2[o][j+k][j],f[o][j][k]);
}
for(int j=1;j<=i;j++)for(int k=i;k>=1;k--){
add(s1[o][j][k],s1[o][j][k+1]);
add(s2[o][j][k],s2[o][j][k+1]);
}
}
for(int i=1;i<=n;i++)for(int j=0;i+j<=n;j++) add(ans,f[o][i][j]);
cout<<ans;
return 0;
}
jzoj 6089 胖
https://jzoj.net/senior/#main/show/6089
正解什么的果然可怕:https://jzoj.net/senior/index.php/main/download/6089/FBCHEF_sol.pdf/0/solution_path
我肯定不会打呀!
暴力出奇迹。
直接和昨天第二题一样每层开一个线段树维护(有多少点开多大)
暴力改,树状数组查询答案
dfn线段树真好。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=1e5+5;
const int MAXM=MAXN*6;
const int inf=1e9;
int n,w[MAXN],q;
int head[MAXN],to[MAXN*2],next[MAXN*2],cnt;
int dfn[MAXN],las[MAXN],tot,dep[MAXN],fa[MAXN],pos[MAXN];
struct Tree{
int c[MAXN];
void add(int x,int v){
for(x;x<=n;x+=x&-x) c[x]+=v;
}
int ask(int x){
int ans=0;
for(x;x;x-=x&-x) ans+=c[x];
return ans;
}
}tr;
struct node{
int v,p;
node(){v=inf,p=0;}
node(int v,int p):v(v),p(p){}
}mn[MAXM];
int lc[MAXM],rc[MAXM],lx[MAXM],rx[MAXM],nd,laz[MAXM];
struct tree{
vector<int>a;
int rt;
void init(){a.push_back(0);}
void ins(int x){a.push_back(x);}
void up(int p){
lx[p]=lx[lc[p]],rx[p]=rx[rc[p]];
mn[p]= mn[lc[p]].v<mn[rc[p]].v ? mn[lc[p]] : mn[rc[p]];
}
void Plus(int p,int v){
if(mn[p].v==inf) return ;
mn[p].v+=v,laz[p]+=v;
}
void down(int p){
if(!laz[p]) return ;
Plus(lc[p],laz[p]),Plus(rc[p],laz[p]);
laz[p]=0;
}
void add(int p,int L,int R,int v){
if(mn[p].v==inf) return ;
if(L<=lx[p]&&rx[p]<=R){Plus(p,v);return ;}
down(p);
if(L<=rx[lc[p]]) add(lc[p],L,R,v);
if(lx[rc[p]]<=R) add(rc[p],L,R,v);
up(p);
}
void build(int &p,int l,int r){
p=++cnt;
if(l==r){
lx[p]=rx[p]=a[l],mn[p]=node(w[pos[a[l]]],a[l]);
return ;
}
int mid=l+r>>1;
build(lc[p],l,mid);
build(rc[p],mid+1,r);
up(p);
}
void change(int p,int x){
if(lx[p]==rx[p]){mn[p].v=inf;return ;}
down(p);
if(x<=rx[lc[p]]) change(lc[p],x);
else change(rc[p],x);
up(p);
}
void keep(){
while(mn[rt].v<=0){
tr.add(mn[rt].p,1);
change(rt,mn[rt].p);
}
}
void pre(){
if(a.size()<=1) return ;
build(rt,1,a.size()-1);keep();
}
}t[MAXN];
void add(int u,int v){
next[++cnt]=head[u],to[cnt]=v,head[u]=cnt;
next[++cnt]=head[v],to[cnt]=u,head[v]=cnt;
}
void dfs(int x,int F){
dfn[x]=++tot,pos[tot]=x,dep[x]=dep[F]+1,fa[x]=F;
t[dep[x]].ins(dfn[x]);
for(int i=head[x];i;i=next[i]){
int y=to[i];
if(y==F) continue;
dfs(y,x);
}
las[x]=tot;
}
void turn(int l,int r,int v,int d){
for(v;v;v/=2,d++){
if(t[d].a.size()==1||r<lx[t[d].rt]||l>rx[t[d].rt]) continue;
t[d].add(t[d].rt,l,r,-v);
t[d].keep();
}
}
void insert(int x,int v){
turn(dfn[x],las[x],v,dep[x]);v/=2;
for(;v;x=fa[x],v/=2){
turn(dfn[fa[x]],dfn[x]-1,v,dep[fa[x]]);
if(las[x]!=las[fa[x]]) turn(las[x]+1,las[fa[x]],v,dep[fa[x]]);
}
}
int main(){
freopen("pang.in","r",stdin);
freopen("pang.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&w[i]),t[i].init();
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),add(u,v);
dfs(1,0);
for(int i=1;i<=n;i++) t[i].pre();
cin>>q;
while(q--){
int op;scanf("%d",&op);
if(op==1){
int A,X;scanf("%d%d",&A,&X);
insert(A,X);
}
if(op==2){
int A;scanf("%d",&A);
printf("%d\n",tr.ask(las[A])-tr.ask(dfn[A]-1));
}
}
return 0;
}
T1后面一扯到数学就全程懵逼。