/*单调队列*/
void dfs(int u,int up,int down)
{
if(up+down>=res)return ;
if(u==n+1)
{
res=min(res,up+down);
return ;
}
int k=0;
while(k<up&&f[k]>=w[u])k++;
int t=f[k];
f[k]=w[u];
if(k>=up)dfs(u+1,up+1,down);
else dfs(u+1,up,down);
f[k]=t;
k=0;
while(k<down&&g[k]<=w[u])k++;
t=g[k];
g[k]=w[u];
if(k>=down)dfs(u+1,up,down+1);
else dfs(u+1,up,down);
g[k]=t;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
res=n;
dfs(1,0,0);
cout<<res;
}
/*多重背包*/
for(int i=0;i<v;i++)
{
int hh=0,tt=-1;
memcpy(g,f,sizeof(f));
for(int j=i;j<=m;j+=v)
{
if(hh<=tt&&q[hh]<j-s*v)hh++;
if(hh<=tt)f[j]=max(f[j],g[q[hh]]+(j-q[hh])/v*w);
while(hh<=tt&&g[q[tt]]-(q[tt]-i)/v*w<=g[j]-(j-i)/v*w)tt--;
q[++tt]=j;
}
}
/*mnancher*/
s[k++]='$',s[k++]='#';
for(int i=0;a[i];i++)s[k++]=a[i],s[k++]='#';
s[k++]='^',n=k;
mr=0,mid;
for(int i=1;i<n;i++)
{
if(i<mr)f[i]=min(f[2*mid-i],mr-i);
else f[i]=1;
while(s[i-f[i]]==s[i+f[i]])f[i]++;
if(i+f[i]>mr)
{
mr=i+f[i];
mid=i;
}
}
/*KMP*/
for(int i=2,j=0;i<=n;i++)
{
while(j&&s[j+1]!=s[i])j=ne[j];
if(s[j+1]==s[i])j++;
ne[i]=j;
}
/*字符串哈希,单哈希*/
typedef unsigned long long ULL
const int P=1331;
ULL p[N],h[N];
ULL get(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}
h[0]=p[0]=1;
for(int i=1;i<=n;i++)
{
p[i]=p[i-1]*P;
h[i]=h[i-1]*P+str[i];
}
/*trie树*/
void insert(string str,int tmp)
{
int p=0;
for(int i=0;i<(int)str.size();i++)
{
int t=str[i]-'a';
if(!tr[p][t])tr[p][t]=++idx;
p=tr[p][t];
}
cnt[p]=tmp;
}
/*并查集*/
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
/*拓扑排序*/
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool tuopu()
{
queue<int> q;
int stk[N],top=0;//记得top要初始化为0
for(int i=1;i<=n;i++)if(!din[i])q.push(i);
while(q.size())
{
int u=q.front();q.pop();
stk[++top]=u;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(--din[j]==0)q.push(j);
}
}
if(top!=n)return false;
else return true;
}
/*组合数学*/
#define int long long
const int mod=1e9+7;
int fact[N],infact[N];
int qmi(int a,int b)
{
int res=1;
while(b)
{
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int C(int n,int m)
{
return fact[n]*infact[n-m]%mod*infact[m]%mod;
}
void init()
{
fact[0]=infact[0]=1;
for(int i=1;i<N;i++)
{
fact[i]=fact[i-1]*i%mod;
infact[i]=infact[i-1]*qmi(i,mod-2)%mod;
}
}
/*floyd(bitset优化)*/
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(f[j][i])f[j]|=f[i];
/*dijkstra*/
void dijkstra(int s)
{
priority_queue<PII,vector<PII>,greater<PII>> heap;
memset(dist,0x3f,sizeof(dist));
dist[s]=0;
heap.push({0,s});
while(heap.size())
{
auto t=heap.top();heap.pop();
int u=t.ys;
if(st[u])continue;
st[u]=true;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[u]+w[i])
{
dist[j]=dist[u]+w[i];
heap.push({dist[j],j});
}
}
}
}
/*ford*/
int ford(int s,int k)
{
memset(dist,0x3f,sizeof(dist));
dist[s]=0;
for(int i=0;i<k;i++)
{
memcpy(back,dist,sizeof(dist));
for(int i=0;i<m+n;i++)
{
int a=e[i].a,b=e[i].b,c=e[i].c;
dist[b]=min(dist[b],back[a]+c);
}
}
return dist[n];
}
/*spfa*/
bool spfa(int s)
{
memset(dist,0x3f,sizeof(dist));
queue<int> q;
q.push(s);
dist[s]=0;
while(q.size())
{
int u=q.front();q.pop();
st[u]=false;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[u]+w[i])
{
dist[j]=dist[u]+w[i];
cnt[j]=cnt[u]+1;
if(cnt>=n)return true;
if(!st[j])q.push(dist[j]),st[j]=true;
}
}
}
return false;
}
/*LCA*/
void dfs(int u,int father)
{
depth[u]=depth[father]+1;
fa[u][0]=father;
for(int i=1;i<=19;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=h[u];~i;i=ne[i];i=ne[i])
{
int j=e[i];
if(j==father)continue;
dfs(j,u);
}
}
int lca(int a,int b)
{
if(depth[a]<depth[b])swap(a,b);
for(int i=19;i>=0;i--)
if(depth[fa[a][i]]>=depth[b])a=fa[a][i];
if(a==b)return a;
for(int i=19;i>=0;i--)
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];
b=fa[b][i];
}
return fa[a][0];
}
/*tarjan*/
void tarjan(int u)
{
dfn[u]=low[u]=++timestamp;
stk[++top]=u,in_stk[u]=true;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!dfn[j])
{
tarjan(j);
low[u]=min(low[u],low[j]);
}
else if(in_stk[j])low[u]=min(low[u],dfn[j]);
}
if(dfn[u]==low[u])
{
++scc_cnt;
int y;
do
{
y=stk[top--];
in_stk[y]=false;
id[y]=scc_cnt;
sized[scc_cnt]++;
}
while(y!=u);
}
}
/*ST表*/
void init()
{
mn[0]=-1;
for(int i=1;i<=n;i++)
{
mn[i]=((i&(i-1))==0)?mn[i-1]+1:mn[i-1];
stmax[i][0]=a[i];
}
for(int i=1;i<=mn[n];i++)
{
for(int j=1;j+(1<<i)-1<=n;j++)
{
stmax[i][j]]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r)
{
int len=r-l+1;
int k=mn[len];
return max(stmax[l][k],stmax[r-(1<<k)+1][k]);
}
/*拆解质因数*/
void init(int n)
{
for(int i=2;i<=n;i++)
{
if(!st[i])primes[++cnt]=i;
for(int j=0;primes[j]<=n/i;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0)break;
}
}
}
/*树状数组*/
int lowbit(int x)
{
return x&(-x);
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i))res+=tr[i];
return res;
}
void modify(int x)
{
for(int i=x;i<=n;i+=lowbit(i))tr[i]+=x;
}
/*差分约束*/
bool spfa(int s)
{
memset(dist,-0x3f,sizeof(dist));
deque<int> q;
q.push_back(s);
dist[s]=0;
while(q.size())
{
auto u=q.back();q.pop_back();
st[u]=false;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(dist[j]<dist[u]+w[i])
{
dist[j]=dist[u]+w[i];
cnt[j]=cnt[u]+1;
if(cnt[j]>=n+1)return false;
if(!st[j])
{
q.push_back(j);
st[j]=true;
}
}
}
}
}
void add(int a,int b,int c)b>=a+c//要求最小值就用最长路,要求最大值就要用最短路,反过来求解
/*树链*/
void dfs1(int u,int father)
{
fa[u]=father;
sz[u]=1;
dep[u]=dep[father]+1;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j==father)continue;
dfs1(j,u);
sz[u]+=sz[j];
if(sz[son[u]]<sz[j])son[u]=j;
}
}
void dfs2(int u,int father)
{
id[u]=++cnt,nw[cnt]=w[u],top[u]=father;
if(!son[u])return ;
dfs2(son[u],father);
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j==fa[u]||son[u]==j)continue;
dfs2(j,j);
}
}
void modify_path(int u,int v,int val)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);
modify(1,id[top[u]],id[u],val);
u=fa[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
modify(1,id[v],id[u],val);
}//query查询操作可以在此基础上进行更改
/*动态开点线段树*/
struct Nodes
{
int l,r,sum;
}tr[N*100];
int root;
void modify(int& root,int l,int r,int x,int val)
{
if(!root)root=++cnt;
if(l==r)
{
tr[root].sum+=val;
}
else
{
int mid=l+r>>1;
if(x<=mid)modify(tr[root].l,l,mid,x,val);
else modify(tr[root].r,mid+1,r,x,val);
pushup(root);
}
}
void query(int root,int l,int r,int pl,int pr)
{
if(!root)return 0;
if(l>=pl&&r<=pr)return tr[root].sum;
else
{
int mid=l+r>>1;
int sum=0;
if(pl<=mid)sum=query(tr[root].l,l,mid,pl,pr);
if(pr>mid)sum+=query(tr[root].r,mid+1,r,pl,pr);
return sum;
}
}
蓝桥基础模板
最新推荐文章于 2025-06-02 22:32:33 发布
659

被折叠的 条评论
为什么被折叠?



