标签:pre 方案 char else efi max bzoj link include
这是一个裸的 树链剖分+线段树
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 30005
#define INF 0x3f3f3f3f
#define ls lson[u]
#define rs rson[u]
#define get(a,u,l,r,al,ar,kd); if(kd==0) a=max(a,query(u,l,r,al,ar,kd));else a+=query(u,l,r,al,ar,kd);
using namespace std;
struct edge{
int to,next;
}e[MAXN<<1];
int lson[MAXN<<1],rson[MAXN<<1],mxn[MAXN<<1],sum[MAXN<<1];
int head[MAXN],sze[MAXN],top[MAXN],val[MAXN],bs[MAXN],xl[MAXN],mp[MAXN],dep[MAXN],fa[MAXN];
int n,m,ent=1,cnt,sz,rt;
void add(int u,int v){
e[ent]=(edge){v,head[u]};
head[u]=ent++;
}
void find_heavy(int u,int f,int deep){
sze[u]=1; dep[u]=deep; fa[u]=f; int mxs=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]) continue;
find_heavy(v,u,deep+1);
sze[u]+=sze[v];
if(sze[v]>mxs) mxs=sze[v],bs[u]=v;
}
}
void connect_heavy(int u,int tp){
top[u]=tp; xl[++cnt]=u; mp[u]=cnt;
if(bs[u]) connect_heavy(bs[u],tp);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]||v==bs[u]) continue;
connect_heavy(v,v);
}
}
void pushup(int u){
mxn[u]=max((ls?mxn[ls]:-INF),(rs?mxn[rs]:-INF));
sum[u]=(ls?sum[ls]:0)+(rs?sum[rs]:0);
}
void build(int &u,int l,int r){
u=++sz;
if(l==r){
mxn[u]=sum[u]=val[xl[l]];
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,int p,int w){
if(l==r){
mxn[u]=sum[u]=w;
return;
}
int mid=(l+r)>>1;
if(p<=mid) modify(ls,l,mid,p,w);
else modify(rs,mid+1,r,p,w);
pushup(u);
}
void change(int a,int b){
int p=mp[a];
modify(rt,1,n,p,b);
}
int query(int u,int l,int r,int al,int ar,int kd){
if(al<=l&&r<=ar) return kd?sum[u]:mxn[u];
int mid=(l+r)>>1,now=kd?0:-INF;
if(al<=mid) {get(now,ls,l,mid,al,ar,kd);}
if(mid<ar) {get(now,rs,mid+1,r,al,ar,kd);}
return now;
}
void answer(int a,int b,int kd){
int ans=kd?0:-INF,l,r;
while(top[a]!=top[b]){
if(dep[top[a]]>dep[top[b]]) swap(a,b);
l=mp[top[b]]; r=mp[b];
if(l>r) swap(l,r);
get(ans,rt,1,n,l,r,kd);
b=fa[top[b]];
}
l=mp[a]; r=mp[b];
if(l>r) swap(l,r);
get(ans,rt,1,n,l,r,kd);
printf("%d\n",ans);
}
int main(){
scanf("%d",&n);
for(int i=1,a,b;i<n;i++){
scanf("%d%d",&a,&b);
add(a,b); add(b,a);
}
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
find_heavy(1,0,1);
connect_heavy(1,1);
build(rt,1,n);
scanf("%d",&m);
char com[10];
for(int i=1,a,b;i<=m;i++){
scanf(" %s %d%d",com,&a,&b);
if(com[1]==‘H‘) change(a,b);
else if(com[1]==‘M‘) answer(a,b,0);
else if(com[1]==‘S‘) answer(a,b,1);
}
return 0;
}
DP神题
dp[i][j][k][l]:放了i个人,有j个男的,
且以i为结尾的所有区间中:男的最多比女的多k个,女的最多比男的多l个 的方案数
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int mod=12345678;
int dp[305][155][25][25];
int n,m,p,ans;
int main(){
scanf("%d%d%d",&n,&m,&p);
dp[0][0][0][0]=1;
for(int i=0;i<n+m;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=p;k++)
for(int l=0;l<=p;l++){
if(j+1<=n&&k+1<=p)
dp[i+1][j+1][k+1][max(l-1,0)]=(dp[i+1][j+1][k+1][max(l-1,0)]+dp[i][j][k][l])%mod;
if(i-j+1<=m&&l+1<=p)
dp[i+1][j][max(k-1,0)][l+1]=(dp[i+1][j][max(k-1,0)][l+1]+dp[i][j][k][l])%mod;
}
for(int k=0;k<=p;k++)
for(int l=0;l<=p;l++)
ans=(ans+dp[n+m][n][k][l])%mod;
printf("%d",ans);
return 0;
}标签:pre 方案 char else efi max bzoj link include
原文地址:http://www.cnblogs.com/zj75211/p/7670034.html