P4315 月下“毛景树”
没代码能力,写不动,赛时没写。
注意 pushdown 即可。
#include<bits/stdc++.h>
inline int read(){
char ch=getchar();int x=0,f=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
const int N=1e5+10;
int n,head[N],tot,dfn[N],top[N],dep[N],son[N],siz[N],fa[N],w[N],rnk[N];
std::pair<int,int> tr[N];
struct E{int v,next,w;}e[N<<1];
inline void add(int u,int v,int w){e[++tot]={v,head[u],w},head[u]=tot;}
inline void dfs1(int x){
siz[x]=1;
int y;
for(int i=head[x];i;i=e[i].next){
if(!dep[y=e[i].v]){
w[y]=e[i].w;
dep[y]=dep[x]+1;fa[y]=x;dfs1(y);siz[x]+=siz[y];
if(!son[x]||siz[y]>siz[son[x]])son[x]=y;
}
}
}
inline void dfs2(int x,int t){
top[x]=t;dfn[x]=++tot;rnk[tot]=x;
if(!son[x])return;
dfs2(son[x],t);
int y;
for(int i=head[x];i;i=e[i].next){
y=e[i].v;
if(y!=fa[x]&&y!=son[x])dfs2(y,y);
}
}
struct Tree{int push,modi,max;}t[N<<2];
inline void pushdown(int p){
if(t[p].push>=0){
t[p<<1].modi=t[p<<1|1].modi=0;
t[p<<1].max=t[p<<1|1].max=t[p<<1].push=t[p<<1|1].push=t[p].push;
}
if(t[p].modi){
t[p<<1].modi+=t[p].modi,t[p<<1|1].modi+=t[p].modi;
t[p<<1].max+=t[p].modi,t[p<<1|1].max+=t[p].modi;
}
t[p].push=-1,t[p].modi=0;
}
inline void update(int p){
t[p].max=std::max(t[p<<1].max,t[p<<1|1].max);
}
inline void build(int p,int l,int r){
t[p].push=-1;
if(l==r){t[p].max=w[rnk[l]];t[p].push=-1;return;}
int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
update(p);
}
inline int ask(int p,int l,int r,int x,int y){
int res=-2e9;
if(l>=x&&r<=y){return t[p].max;}
pushdown(p);
int mid=l+r>>1;
if(x<=mid)res=std::max(res,ask(p<<1,l,mid,x,y));
if(y>mid)res=std::max(res,ask(p<<1|1,mid+1,r,x,y));
return res;
}
inline int query(int u,int v){
int res=-2e9;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])std::swap(u,v);
res=std::max(res,ask(1,1,n,dfn[top[u]],dfn[u]));
u=fa[top[u]];
}
if(u==v)return res;
if(dep[u]>dep[v])std::swap(u,v);
res=std::max(res,ask(1,1,n,dfn[son[u]],dfn[v]));
return res;
}
inline void change1(int p,int l,int r,int x,int y,int c){
if(l>=x&&r<=y){t[p].modi+=c;t[p].max+=c;return;}
pushdown(p);
int mid=l+r>>1;
if(x<=mid)change1(p<<1,l,mid,x,y,c);
if(y>mid)change1(p<<1|1,mid+1,r,x,y,c);
update(p);
}
inline void change2(int p,int l,int r,int x,int y,int c){
if(l>=x&&r<=y){t[p].modi=0;t[p].push=c;t[p].max=c;return;}
pushdown(p);
int mid=l+r>>1;
if(x<=mid)change2(p<<1,l,mid,x,y,c);
if(y>mid)change2(p<<1|1,mid+1,r,x,y,c);
update(p);
}
inline void modify(int u,int v,int c,int flag){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])std::swap(u,v);
if(flag)change1(1,1,n,dfn[top[u]],dfn[u],c);
else change2(1,1,n,dfn[top[u]],dfn[u],c);
u=fa[top[u]];
}
if(u==v)return;
if(dep[u]>dep[v])std::swap(u,v);
if(flag)change1(1,1,n,dfn[son[u]],dfn[v],c);
else change2(1,1,n,dfn[son[u]],dfn[v],c);
}
int main(){
// freopen("in.in","r",stdin),freopen("out.out","w",stdout);
std::ios::sync_with_stdio(false);std::cin.tie(0),std::cout.tie(0);
std::cin>>n;
dep[1]=1;
for(int i=1;i<n;++i){
int u,v,w;std::cin>>u>>v>>w;
tr[i]={u,v};
add(u,v,w);add(v,u,w);
}
dfs1(1);tot=0;
dfs2(1,1);
build(1,1,n);
while(1){
std::string s;
std::cin>>s;
if(s=="Max"){
int u,v;std::cin>>u>>v;
std::cout<<query(u,v)<<"\n";
}
if(s=="Change"){
int k,c;std::cin>>k>>c;
modify(tr[k].first,tr[k].second,c,0);
}
if(s=="Cover"){
int u,v,c;std::cin>>u>>v>>c;
modify(u,v,c,0);
}
if(s=="Add"){
int u,v,c;std::cin>>u>>v>>c;
modify(u,v,c,1);
}
if(s=="Stop"){
exit(0);
}
}
}
上课安排
考虑数学归纳法。
- \(n=5\) 时,可以找出 \(\{1\},\{2,3\},\{3,4,5\}\),对于 \(n=7\) 时,可以在每个集合后加一个 \(7\),然后将 \(6\) 作为一个单独的集合,再加上一个 \(\{1,2,3,4,5\}\) 这样的集合。对于所有奇数,以此类推。
- \(n=4\) 时,可以找出 \(\{1\},\{2,3\}\),对于 \(n=6\) 时,可以在每个集合后加一个 \(7\),然后将 \(5\) 作为一个单独的集合,再加上 \(\{1,2,3,4\}\) 这样的集合。对于所有偶数,以此类推。
代码是打表找的规律(赛时快读锅了)。
#include<bits/stdc++.h>
inline int read(){
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<'9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
const int N=1e3+10;
int main(){
freopen("course.in","r",stdin);freopen("course.out","w",stdout);
int n;
std::cin>>n;
int ans=n-2;
std::cout<<ans<<'\n';
if(n&1){
for(int i=1;i<=ans;++i){
std::cout<<i<<' ';
if(i<=n/2){
int zc=n-(i*2-1);
std::cout<<zc<<' ';
zc+=3;
for(int j=1;j<=i-1;++j,zc+=2)std::cout<<zc<<' ';std::cout<<'\n';
}
else{
int zc=i-n/2+1;zc=zc*2-1;
for(int j=1;j<=zc;++j)std::cout<<j<<' ';
int w=zc+4;
for(;w<=n;w+=2)std::cout<<w<<' ';std::cout<<'\n';
}
}
}else{
for(int i=1;i<=ans;++i){
std::cout<<i<<' ';
if(i<=n/2){
int zc=n-(i*2-1);
std::cout<<zc<<' ';
zc+=3;
for(int j=1;j<=i-1;++j,zc+=2)std::cout<<zc<<' ';std::cout<<'\n';
}
else{
int zc=i-n/2+1;zc=zc*2;
for(int j=1;j<=zc;++j)std::cout<<j<<' ';
int w=zc+4;
for(;w<=n;w+=2)std::cout<<w<<' ';std::cout<<'\n';
}
}
}
}
P3360 偷天换日
递归输入建图,然后对于叶子做背包,向父亲直接枚举转移即可(赛时快读锅了)。
#include<bits/stdc++.h>
#define int long long
inline int read(){
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
const int N=705;
int f[N][N],tot,head[N],max,cnt=1,a[N],v[N],b[305][40][N],lson[N],rson[N],wlson[N],wrson[N];
struct E{int v,next,w;}e[N];
inline void add(int u,int v,int w){w*=2;e[++tot]={v,head[u],w};head[u]=tot;}
inline void bp(int x,int t){
int zc=0;
for(int i=1;i<=t;++i){
a[i]=read(),v[i]=read();
zc+=v[i];
}
b[x][1][v[1]]=a[1];
for(int i=2;i<=t;++i){
for(int j=0;j<=zc;++j){
b[x][i][j]=b[x][i-1][j];
if(j>=v[i]){
b[x][i][j]=std::max(b[x][i][j],b[x][i-1][j-v[i]]+a[i]);
}
}
}
for(int i=0;i<=zc;++i)f[x][i]=b[x][t][i];
}
inline void init(int x){
int w=read();
add(x,++cnt,w);
int zc=cnt;
int t=read();
if(!t){
init(zc);
init(zc);
}else{
bp(zc,t);
}
}
inline void dfs(int x){
if(lson[x]){
dfs(lson[x]);
for(int i=0;i+wlson[x]<=max;++i){
f[x][i+wlson[x]]=f[lson[x]][i];
}
}
if(rson[x]){
dfs(rson[x]);
for(int i=max;i>=0;--i){
for(int k=1;k<=i;++k){
if(i+wrson[x]>max)continue;
f[x][i+wrson[x]]=std::max(f[x][i+wrson[x]],f[x][i-k]+f[rson[x]][k]);
}
}
}
}
signed main(){
// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
max=read()-1;init(1);
for(int i=1;i<=cnt;++i){
int j=head[i];
if(!j){continue;}
lson[i]=e[j].v;wlson[i]=e[j].w;
j=e[j].next;
if(j)rson[i]=e[j].v,wrson[i]=e[j].w;
}
dfs(1);
int ans=0;
for(int i=max;i>=0;--i){
if(f[1][i]){
ans=std::max(f[1][i],ans);
}
}
std::cout<<ans<<'\n';
}
P2894 [USACO08FEB] Hotel G
发的题解是线段树合并,但我感觉没那意思。
跟山海经(小白逛公园)有些相似,考虑维护区间最长 \(0\) 的连续段,修改直接做,对于查询如果当前节点不满足则不合法,满足则查找左儿子,如果左儿子的值满足直接进去找,否则就是当前节点的答案。
赛时没代码能力,没写动,写了个有些唐氏的暴力(比较难卡)。等会补正解。
#include <bits/stdc++.h>
inline int read() {
int x = 0, f = 1;
char ch = getchar();
for (; ch < '0' || ch > '9'; ch = getchar())
if (ch == '-')
f = -1;
for (; ch >= '0' && ch <= '9'; ch = getchar())
x = x * 10 + ch - '0';
return x * f;
}
const int N = 5e4 + 10;
int n, m, a[N];
inline void write(int x) {
if (x >= 10) {
write(x / 10);
}
putchar(x % 10 + '0');
}
signed main() {
freopen("hotel.in", "r", stdin);
freopen("hotel.out", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
n = read(), m = read();
for (int i = 1; i <= m; ++i) {
int op = read();
if (op == 1) {
int l = read();
bool flag = 0;
for (int j = 1; j + l - 1 <= n; ++j) {
if (a[j] || a[j + l - 1])
continue;
int zc = 0;
for (int k = j; k <= j + l - 1; ++k) {
if (a[k]) {
j = k;
break;
} else
zc++;
}
if (zc == l) {
write(j);
putchar('\n');
flag = 1;
for (int k = j; k <= j + l - 1; ++k)
a[k] = 1;
break;
}
}
if (!flag)
write(0), putchar('\n');
} else {
int l = read(), r = read();
r = l + r - 1;
for (int j = l; j <= r; ++j)
a[j] = 0;
}
}
}
P4303 [AHOI2006] 基因匹配
赛时没咋看,感觉比前面四道加起来有深意。
根据性质,每个数出现 \(5\) 次,所以只会在这 \(5\) 个位置匹配成功。
具体来说,记一下 \(a\) 串的每个数出现的位置,设 \(f_i\) 表示匹配到 \(a\) 串的第 \(i\) 个位置时的最长 LCS 长度,然后遍历 \(b\) 串,查找 \(b_i\) 在 \(a\) 串中的位置 \(x\),有 \(f_x=\max(f_k+1)(k\le x-1)\),(注意倒序)上数据结构维护即可。
#include<bits/stdc++.h>
inline int read(){
char ch=getchar();int x=0,f=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
const int N=1e5+10;
int n,f[N];
std::vector<int> v_a[N],v_b[N];
struct Tree{int ans;}t[N<<2];
inline void change(int p,int l,int r,int pos,int x){
if(l==r){t[p].ans=x;return;}
int mid=l+r>>1;
if(pos<=mid)change(p*2,l,mid,pos,x);
else change(p*2+1,mid+1,r,pos,x);
t[p].ans=std::max(t[p*2].ans,t[p*2+1].ans);
}
inline int query(int p,int l,int r,int x,int y){
if(x>y)return 0;
if(l>=x&&r<=y)return t[p].ans;
int mid=l+r>>1,res=0;
if(x<=mid)res=std::max(res,query(p*2,l,mid,x,y));
if(y>mid)res=std::max(res,query(p*2+1,mid+1,r,x,y));
return res;
}
int main(){
// freopen("match.in","r",stdin),freopen("match.out","w",stdout);
std::ios::sync_with_stdio(false);std::cin.tie(0),std::cout.tie(0);
n=read();
for(int i=1;i<=n*5;++i){
int x=read();v_a[x].push_back(i);
}
for(int i=1;i<=n;++i)std::reverse(v_a[i].begin(),v_a[i].end());
n*=5;
int ans=0;
for(int i=1;i<=n;++i){
int x=read();
for(int y:v_a[x]){
f[y]=std::max(f[y],query(1,1,n,1,y-1)+1);
change(1,1,n,y,f[y]);
ans=std::max(ans,f[y]);
}
}
std::cout<<ans<<'\n';
}
标签:std,ch,int,题解,read,&&,模拟,getchar
From: https://www.cnblogs.com/Ishar-zdl/p/18235961