8.9
P13557
AT_abc416_f [ABC416F] Paint Tree 2
P13557
赛时转成曼哈顿距离后人傻了

发现如果鱼在红色箭头处,朝箭头所指方向游动,那么只要把网布在蓝色区域就可以捉到(蓝色区域可向上,下,右无限延伸)
也就是只要做二维差分就可以了,但是注意数据范围,发现横纵坐互不影响,分别离散化后计算, 取两个前缀和数组中的最大值相加
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int inf=1e5+1;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
void read(char& c){
do{
c=getchar();
}while(c==10||c==13);
}
int x[maxn],y[maxn];
int xt[maxn],yt[maxn];
char d[maxn];
int n;
vector<int> v;
void ls(int* a){
v.resize(0);
for(int i=1;i<=n;i++){
v.push_back(a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;i++){
a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
}
}
int main(){
int t;
read(t);
while(t--){
read(n);
for(int i=1;i<=n;i++){
read(x[i]),read(y[i]),read(d[i]);
}
ls(x),ls(y);
memset(xt,0,sizeof(xt)),memset(yt,0,sizeof(yt));
for(int i=1;i<=n;i++){
if(d[i]=='L') ++xt[1],--xt[x[i]+1];
else if(d[i]=='R') ++xt[x[i]];
else if(d[i]=='D') ++yt[1],--yt[y[i]+1];
else ++yt[y[i]];
}
int ansx=0,ansy=0;
for(int i=1;i<=inf;i++){
xt[i]+=xt[i-1],yt[i]+=yt[i-1];
ansx=max(ansx,xt[i]),ansy=max(ansy,yt[i]);
}
printf("%d\n",ansx+ansy);
}
return 0;
}
//^o^
50%完成,今晚要打abc了
AT_abc416_f [ABC416F] Paint Tree 2
8.10补
k很小,想到树上dp
设计状态dp[maxn][6][3]
第一维:当前的点
第二维:已经选取的路径数
第三维:当前的点,0不在链上,1在一条链上的端点,2在链上却不是端点
枚举当前选取的边数以及该子节点所占得边数
以下转移中mx=max({dp[v][j][0],dp[v][j][1],dp[v][j][2]})
若j为0,则mx=dp[v][j][0]
五种转移:
一,2状态可以由1状态再加上当前子节点的1状态合并而来,前提是当前节点的1状态不能只选0条路径
if(j) dp[u][i][2]=max(dp[u][i][2],dp[u][i-j+1][1]+dp[v][j][1]);
二,2状态可以由2状态再加上当前子节点的任意状态,前提是当前节点的2状态不能只选0条路径
if(i-j) dp[u][i][2]=max(dp[u][i][2],dp[u][i-j][2]+mx);
三,1状态可以由1状态再加上当前子节点的任意状态,前提是当前节点的1状态不能只选0条路径
if(i-j) dp[u][i][1]=max(dp[u][i][1],dp[u][i-j][1]+mx);
四,1状态可以由当前子节点的1状态向上加上该端点得来,前提是当前子节点的1状态不能只选0条路径
dp[u][i][0]=max(dp[u][i][0],dp[u][i-j][0]+mx);
五,0状态可以由0状态再加上当前子节点的任意状态,没有前提
dp[u][i][0]=max(dp[u][i][0],dp[u][i-j][0]+mx);
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=2e5+5;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
void read(char& c){
do{
c=getchar();
}while(c==10||c==13);
}
int head[maxn],nxt[maxn<<1],e[maxn<<1];
int mp_cnt;
void init_mp(){
memset(head,-1,sizeof(head));
mp_cnt=-1;
}
void add_edge(int u,int v){
e[++mp_cnt]=v;
nxt[mp_cnt]=head[u];
head[u]=mp_cnt;
}
int n,k;
LL dp[maxn][6][3];
int a[maxn];
void dfs(int u,int fa){
dp[u][1][1]=a[u];
for(int i=head[u];~i;i=nxt[i]){
int v=e[i];
if(v==fa) continue;
dfs(v,u);
for(int i=k;i>=0;i--){
for(int j=0;j<=i;j++){
LL mx=max({dp[v][j][0],dp[v][j][1],dp[v][j][2]});
if(!j) mx=dp[v][j][0];
if(j) dp[u][i][2]=max(dp[u][i][2],dp[u][i-j+1][1]+dp[v][j][1]);
if(i-j) dp[u][i][2]=max(dp[u][i][2],dp[u][i-j][2]+mx);
if(i-j) dp[u][i][1]=max(dp[u][i][1],dp[u][i-j][1]+mx);
if(j) dp[u][i][1]=max(dp[u][i][1],dp[u][i-j][0]+dp[v][j][1]+a[u]);
dp[u][i][0]=max(dp[u][i][0],dp[u][i-j][0]+mx);
}
}
}
}
int main(){
read(n),read(k);
for(int i=1;i<=n;i++){
read(a[i]);
}
int u,v;
init_mp();
for(int i=1;i<n;i++){
read(u),read(v);
add_edge(u,v),add_edge(v,u);
}
dfs(1,1);
LL ans=0;
for(int i=0;i<=k;i++){
ans=max(ans,max({dp[1][i][0],dp[1][i][1],dp[1][i][2]}));
}
printf("%lld",ans);
return 0;
}
//^o^

浙公网安备 33010602011771号