唉其实 Zpair 出的模拟赛除了没做上都挺有意思
[POI2011]LIZ-Lollipop
题意:给一个只有1和2的序列,每次询问有没有一个子串的和为x
奇妙性质题
性质1:如果 s 可以到达,那么 s-2 必定可以到达
证明:考虑左右两边都是 1 ,就删掉左右两端的数,要不就删掉一个 2
经典说出来觉得很 ** ,但是就是想不到的性质
那么就分奇偶考虑,与全选相同奇偶性且比全选小的一定可以,然后就考虑另外一种情况。
如果删掉一个 2 对奇偶性没有影响,只有删掉 1 才有,所以就是找到离左右端点最近的一,然后只从一端开始删,直到走到那个 1 ,这是另外一种奇偶性能走到的最大值
然后方案就是上面那种方法走一遍就行
[POI2015] WIL
嗯我单调队列应该复习一下的
从左向右枚举 r ,可以发现 l 一定单调不降(指选中的区间)。然后就需要一个双指针。对于 \(l\sim r\) 的范围内,你需要维护一个区间内 \(sum[i]-sum[i-d]\) 的最大值,于是你需要一个单调队列。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,d;ll p;
const int maxn=4000020;
ll a[maxn];int q[maxn];
int main()
{
scanf("%d%d%d",&n,&p,&d);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]+=a[i-1];
int l=1,ans=d;int h=1,t=1;
q[1]=d;
for(int i=d+1;i<=n;i++)
{
while(h<=t&&a[q[t]]-a[q[t]-d]<a[i]-a[i-d]) t--;
q[++t]=i;
while(h<=t&&a[i]-a[l-1]-a[q[h]]+a[q[h]-d]>p)
{
l++;
while(h<=t&&q[h]-d+1<l) h++;
}
ans=max(ans,i-l+1);
}
printf("%d\n",ans);
}
[HEOI2013]SAO
妙妙树形 DP
首先不考虑树的边的方向,那么就是一棵树。树的话,设 DP 状态为 \(f_{i,j}\) 表示第 \(i\) 个节点,当前节点在 \(i\) 的子树内排名第 \(j\) 的方案数。
然后考虑怎么将新来的一棵子树 \(v\) 加入到他的父亲上。
首先是考虑 \(a[p]<a[v]\) 的情况,我们现在要转移到 \(f_{p,k}\) ,我们要枚举 \(j\) 表示在插入新子树前的 \(p\) 的排名,再枚举 \(l\) 表示 \(v\) 在它自己的子树上的排名。因为在 \(p\) 前面要填满 \(k\) 个,而它前面已经有 \(j\) 个了,所以 \(l \geq k-j\)
首先考虑 \(p,v\) 前面的情况,就是最后在 \(p\) 前有 \(k-1\) 个数,而一开始有 \(j-1\) 个,所以前面的方案数的贡献为 \(C_{k-1}^{j-1}\) ,然后考虑在后面的情况,就是在 \(p\) 后面有 \(siz[p]+siz[v]-k\) 个数,然后一开始有 \(siz[p]-j\) 个,所以这部分贡献的答案为 \(C_{siz[p]+siz[v]-k}^{siz[p]-j}\)
然后写出来就是 \(\displaystyle f_{p,k}=\sum_{j=1}^{siz[p]}\sum_{l=k-j}^{siz[v]} f_{p,j}f_{v,l}C_{siz[p]+siz[v]-k}^{siz[p]-j}C_{k-1}^{j-1}\)
\(a[p]>a[v]\) 的情况同理。
这个复杂度是 \(n^3\) 的吧
然后那一坨式子带 \(p\) 的都提出来,剩下的就前缀和优化一下。变成 \(O(n^2)\) 的
[COCI2021-2022#2] Osumnjičeni
对于要查询的 \(l,r\) ,对于 \(l\) 贪心地一定要去找尽可能长的右端点去跳。
那么就要先求出对于每一个 \(l\), 那个最远的区间能到哪里。我们用单调队列加线段树维护。当加入一个区间时,在权值线段树上查询有无交叉的区间。如果有就弹出队首并记录下队首的最远距离。
然后是个优秀的套路
给你一堆区间,问需要最少多少区间能够将一段给定区间覆盖。我们使用倍增,\(f[i][j]\) 表示 \(i\) 为起点,跳 \(2^j\) 步能跳到的区间头。
然后倍增地找就行了
然后这个性质的话应该是这个题 CF1175E
#include <bits/stdc++.h>
using namespace std;
const int maxn=4000200;
int n,lx[maxn],rx[maxn];
int c[maxn*8],lzy[maxn];
#define lson(p) ((p)<<1)
#define rson(p) ((p)<<1|1)
void pushdown(int p,int l,int r)
{
int mid=(l+r)>>1;
c[lson(p)]+=(mid-l+1)*lzy[p]; c[rson(p)]+=(r-mid)*lzy[p];
lzy[lson(p)]+=lzy[p];lzy[rson(p)]+=lzy[p];
lzy[p]=0;
}
void update(int l,int r,int x,int y,int v,int p)
{
if(x<=l&&y>=r)
{
c[p]+=(r-l+1)*v; lzy[p]+=v;return;
}
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,y,v,lson(p));
if(y>mid) update(mid+1,r,x,y,v,rson(p));
c[p]=(c[lson(p)]+c[rson(p)]);
}
int query(int l,int r,int x,int y,int p)
{
if(x<=l&&y>=r) return c[p];
int mid=(l+r)>>1,ret=0;
if(lzy[p]) pushdown(p,l,r);
if(x<=mid) ret+=query(l,mid,x,y,lson(p));
if(y>mid) ret+=query(mid+1,r,x,y,rson(p));
return ret;
}
int f[maxn][21];int a[maxn],cnt,q[maxn];
int main()
{
// freopen("p.in","r",stdin);
//freopen("p.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&lx[i],&rx[i]);
a[++cnt]=lx[i];a[++cnt]=rx[i];
}
sort(a+1,a+1+cnt);int ccnt=unique(a+1,a+1+cnt)-a;
for(int i=1;i<=n;i++)
{
lx[i]=lower_bound(a+1,a+1+ccnt,lx[i])-a;
rx[i]=lower_bound(a+1,a+1+ccnt,rx[i])-a;
}
int l=1,r=0;
for(int i=1;i<=n;i++)
{
while(r>=1&&query(1,2*n,lx[i],rx[i],1))
{
f[l][0]=i;update(1,2*n,lx[q[l]],rx[q[l]],-1,1);
l++;
}
q[++r]=i;
update(1,2*n,lx[i],rx[i],1,1);
}
for(int i=l;i<=r;i++) f[q[i]][0]=n+1;
f[n+1][0]=n+1;
for(int i=n+1;i>=1;i--)
{
for(int j=1;j<=20;j++) f[i][j]=f[f[i][j-1]][j-1];
}
int Q;scanf("%d",&Q);
while(Q--)
{
int p,q;scanf("%d%d",&p,&q);
int ans=1;
for(int i=20;i>=0;i--)
{
if(f[p][i]<=q) p=f[p][i],ans+=(1<<i);
}
printf("%d\n",ans);
}
}
废话
嘛,没啥,嗯,就是,没啥要说的。早点休息,没什么要顾虑的就是了
标签:lzy,9.16,siz,rson,mid,int,maxn,小记 From: https://www.cnblogs.com/cc0000/p/16728390.html自由的夏虫编织着美梦解渴
单薄的外壳 展开花纹
尽将内心诉说
鞘翅振涌
卷起击碎定论的漩涡
等待 数百天伏蛰
这一瞬冲破
最高亢的歌 予我
肆意鸣唱
直到 嘶哑那刻