A - Diversity HDU - 6725 (树形dp)
若两个区间有交,显然可以把两个区间的值,都取在区间交集的端点的其中一个,
若没有交集的话,[l1,r1]<[l2,r2]时,取到r1和l2,也在区间的端点
因此,[l,r]的数,只由两端点决定,二选一,树形dp
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int N=1e5+10;
int t,n,u,v;
vector<int>E[N];
ll dp[N][2],a[N][2];
void dfs(int u,int fa)
{
for(int i=0;i<E[u].size();++i)
{
int v=E[u][i];
if(v==fa)continue;
dfs(v,u);
for(int j=0;j<2;++j)
dp[u][j]+=max(dp[v][1]+abs(a[u][j]-a[v][1]),dp[v][0]+abs(a[u][j]-a[v][0]));
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
E[i].clear();
dp[i][0]=dp[i][1]=0;
}
for(int i=1;i<n;++i)
{
scanf("%d%d",&u,&v);
E[u].pb(v),E[v].pb(u);
}
for(int i=1;i<=n;++i)
scanf("%lld%lld",&a[i][0],&a[i][1]);
dfs(1,-1);
printf("%lld\n",max(dp[1][0],dp[1][1]));
}
return 0;
}
B - Transformation HDU - 6726 (数学/找规律)
赛后补题,
第一次操作,(a,b+(b-a))或(a+(a-b),b),要么前项加(a-b),要么后项加(b-a)
第二次操作,要么前项加2*(a-b),要么后项加2*(b-a)
第三次操作,要么前项加4*(a-b),要么后项加4*(b-a)
所以,c-a必须是a-b的倍数,d-b必须是a-b的倍数
特判a=b的情形,再讨论x=(c-a)/(a-b)和y=(d-b)/(a-b),显然答案唯一,与字典序无关
x和y非负且不能有交集,且x与y的并集构成二进制形如000001111111111的序列
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll a,b,c,d,x,y;
bool ok(ll x)//判断x是否形如000111111 右起一段连续的1
{
x++;
x-=x&-x;
return x==0;
}
int main()
{
scanf("%d",&t);
while(t--)
{
//每次操作 必a+=k*(a-b) 或b+=k*(b-a) k为2的幂次且从1起不断*2
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);//c-a=x*(a-b) d-b=y*(b-a) x和y二进制无交集
if(a==b)//c和d不会改变
{
if(c==a&&d==b)printf("Yes\n\n");
else puts("No");
continue;
}
if((c-a)%(a-b)||(d-b)%(b-a))
{
puts("No");
continue;
}
x=(c-a)/(a-b);y=(d-b)/(b-a);
if(x<0||y<0||(x&y)||!ok(x|y))
{
puts("No");
continue;
}
puts("Yes");
for(int i=0;(x>>i&1)|(y>>i&1);i++)
{
if(x>>i&1)putchar('B');
else putchar('A');
}
puts("");
}
return 0;
}
C - Quasi Binary Search Tree HDU - 6727 (二叉树/构造)
赛中AC,纪念一下
对于一棵子树来讲,其值一定是连续的,
所以子树值一定会被分成三段,[l,x],x+1,[x+2,r]
op[u]=0代表这棵子树中值最小的值出现在左子树,
op[u]=1代表出现在右子树
op[u]=2代表出现在根,根的时候分左子和右子的数量来讨论
数量相等时,再分左子和右子的最小值哪个小来讨论
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#define fi first
#define se second
#define pb push_back
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+10;
int t,n;
int rt,mn[N],op[N],sz[N],res[N];
int ls[N],rs[N],in[N];
int bs[N];
void init()
{
bs[1]=233;
for(int i=2;i<N;++i)
bs[i]=(1ll*bs[i-1]*233)%mod;
}
void dfs(int u)
{
sz[u]=1;
if(ls[u])
{
dfs(ls[u]);
sz[u]+=sz[ls[u]];
if(mn[ls[u]]<mn[u])
{
mn[u]=mn[ls[u]];
op[u]=0;
}
}
if(rs[u])
{
dfs(rs[u]);
sz[u]+=sz[rs[u]];
if(mn[rs[u]]<mn[u])
{
mn[u]=mn[rs[u]];
op[u]=1;
}
}
if(u<mn[u])
{
mn[u]=u;
op[u]=2;
}
}
void dfs2(int u,int l,int r)
{
if(!u||l>r)return;
if(l==r)
{
res[u]=l;
return;
}
if(op[u]==0)
{
res[u]=l+sz[ls[u]];
dfs2(ls[u],l,l+sz[ls[u]]-1);
dfs2(rs[u],l+sz[ls[u]]+1,r);
}
else if(op[u]==1)
{
res[u]=l+sz[rs[u]];
dfs2(rs[u],l,l+sz[rs[u]]-1);
dfs2(ls[u],l+sz[rs[u]]+1,r);
}
else
{
if(l+sz[ls[u]]<l+sz[rs[u]])
{
res[u]=l+sz[ls[u]];
dfs2(ls[u],l,l+sz[ls[u]]-1);
dfs2(rs[u],l+sz[ls[u]]+1,r);
}
else if(l+sz[ls[u]]>l+sz[rs[u]])
{
res[u]=l+sz[rs[u]];
dfs2(rs[u],l,l+sz[rs[u]]-1);
dfs2(ls[u],l+sz[rs[u]]+1,r);
}
else
{
res[u]=l+sz[ls[u]];
if(mn[ls[u]]<mn[rs[u]])
{
dfs2(ls[u],l,l+sz[ls[u]]-1);
dfs2(rs[u],l+sz[ls[u]]+1,r);
}
else if(mn[ls[u]]>mn[rs[u]])
{
dfs2(rs[u],l,l+sz[rs[u]]-1);
dfs2(ls[u],l+sz[rs[u]]+1,r);
}
}
}
}
int main()
{
init();
mn[0]=INF;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
in[i]=ls[i]=rs[i]=sz[i]=0,mn[i]=n+1;
for(int i=1;i<=n;++i)
{
scanf("%d%d",&ls[i],&rs[i]);
in[ls[i]]++,in[rs[i]]++;
}
for(int i=1;i<=n;++i)
{
if(!in[i])
{
rt=i;
break;
}
}
dfs(rt);
dfs2(rt,1,n);
ll ans=0;
for(int i=1;i<=n;++i)
ans=(ans+(res[i]^i)*1ll*bs[i]%mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
/*
2
5
0 0
0 5
1 0
2 3
0 0
5
0 0
0 0
0 4
2 0
1 3
*/