E. Kojiro and Furrari
题意说的是 在一条直线上 有n个加油站, 每加一单位体积的汽油 可以走1km 然后每个加油站只有一种类型的汽油,汽油的种类有3种 求从起点出发到达终点要求使用最少的 1 号汽油的前提下使用最少的二号汽油,
我们可以这样考虑
当前在第i个加油站的时候         i个加油站 有3种情况
第一种 他是只有 1 号汽油 那么他必须携带 尽量少的 1号汽油到达离他最近的2号汽油点或者3号汽油点 更新这个点到达终点的代价 取最小值,因为他必须通过那个点到达其他点
第二种 他只有 2 号汽油, 那么他必须携带 尽量多的 2号汽油到达能达到的最远的1号汽油点,这样可以更少使用1号汽油,或者 带尽量少的汽油到达离他最近的3号汽油的点,或者最近的2号汽油的点
第三种 如果他是3号汽油 那么他必须携带尽量少的3号汽油到达离他最近的点,或者带尽量多的3号汽油到达离他能达到的最远的1 、2号汽油点
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn=;
const int INF=;
struct point{
int x,t;
point(int cx=, int ct=){
x=cx; t=ct;
}
bool operator <(const point &rhs)const{
return x<rhs.x;
}
}P[maxn];
int D[][maxn],num[];
int dp[maxn][];
int e,s,n,m;
int bitlook1(int x,int *C, int n)
{
int L=,R=n-,ans=-;
while(L<=R)
{
int mid=(L+R)>>;
int id=C[mid];
if( P[id].x>=x ){
ans=mid;
R=mid-;
}else{
L=mid+;
}
}
return ans;
}
void cmp(int &A, int &B,int &V, int C, int D, int DV)
{
if(A>=C){
if(A==C){
if(B<D) return ;
if(B>D){
B=D;
V=DV;
}else{
V=min(V,DV);
}
}
else {
A=C; B=D;
V=DV;
}
}
}
void solve1(int id)
{
int loc=P[id].x;
int d1=bitlook1(loc+,D[],num[]);
int d2=bitlook1(loc+,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1];
if( d3!=- && P[d3].x <= loc+s )
{
int cp1 = dp[d3][]+P[d3].x-loc;
int cp2 = dp[d3][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d3].x-loc);
}
if(d2!=- && P[d2].x<=loc+s)
{
int cp1 = dp[d2][]+P[d2].x-loc;
int cp2 = dp[d2][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d2].x-loc);
}
if( d1!=- && P[d1].x<=loc+s)
{
int cp1 = dp[d1][]+P[d1].x-loc;
int cp2 = dp[d1][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d1].x-loc);
}
}
int bitlook2(int x,int *C, int n)
{
int L=,R=n-,ans=-;
while(L<=R)
{
int mid=(L+R)>>;
int id=C[mid];
if( P[id].x<=x ){
ans=mid;
L=mid+;
}else{
R=mid-;
}
}
return ans;
}
void solve2(int id)
{
int loc=P[id].x;
int d1=bitlook2(loc+s,D[],num[]);
int d2=bitlook1(loc+,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1];
if( d3!=- && P[d3].x <= loc+s )
{
int cp1 = dp[d3][];
int cp2 = dp[d3][]+P[d3].x-loc;
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d3].x-loc);
}
if(d2!=- && P[d2].x<=loc+s)
{
int cp1 = dp[d2][];
int cp2 = dp[d2][]+P[d2].x-loc;
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,P[d3].x-loc);
} if( d1!=-&&P[d1].x>loc)
{
int cp0=s;
int lit = s-(P[d1].x-loc);
int cp1 = dp[d1][]-min(lit,dp[d1][]);
int cp2 = dp[d1][]+cp0;
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,cp0);
}
}
void solve3(int id)
{
int loc=P[id].x;
int d1=bitlook2(loc+s,D[],num[]);
int d2=bitlook2(loc+s,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1]; if( d3!=- && P[d3].x<=loc+s )
{
cmp(dp[id][],dp[id][],dp[id][],dp[d3][],dp[d3][],);
}
if(d2!=-&&P[d2].x>loc)
{
int lit = s-(P[d2].x-loc);
int cp1 = dp[d2][];
int cp2 = dp[d2][]-min(dp[d2][],lit);
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,);
}
if(d1!=-&&P[d1].x>loc)
{
int lit = s-(P[d1].x-loc);
int cp1 = dp[d1][]-min(dp[d1][],lit);
int cp2 = dp[d1][];
cmp(dp[id][],dp[id][],dp[id][],cp1,cp2,);
}
}
void solve4(int loc, int &S1,int &S2)
{
int k;
int d1=bitlook2(loc+s,D[],num[]);
int d2=bitlook2(loc+s,D[],num[]);
int d3=bitlook1(loc+,D[],num[]);
if(d3!=-)d3=D[][d3];
if(d2!=-)d2=D[][d2];
if(d1!=-)d1=D[][d1];
if( d3!=- && P[d3].x<=loc+s &&dp[d3][]!=INF)
{
cmp(S1,S2,k,dp[d3][],dp[d3][],);
}
if(d2!=-&&P[d2].x>loc&&dp[d2][]!=INF)
{
int lit = s-(P[d2].x-loc);
int cp1 = dp[d2][];
int cp2 = dp[d2][]-min(dp[d2][],lit);
cmp(S1,S2,k,cp1,cp2,);
}
if(d1!=-&&P[d1].x>loc&&dp[d1][]!=INF)
{
int lit = s-(P[d1].x-loc);
int cp1 = dp[d1][]-min(dp[d1][],lit);
int cp2 = dp[d1][];
cmp(S1,S2,k,cp1,cp2,);
}
}
int main()
{
while(scanf("%d%d%d%d",&e,&s,&n,&m)==)
{
num[]=num[]=num[]=num[]=;
int k=;
for(int i=; i<n; i++) {
scanf("%d%d",&P[k].t,&P[k].x);
if(P[k].x<e)k++;
}
n=k;
sort(P,P+n);
if(P[n-].x!=e)
{
P[n]=point(e,);
n++;
}
for(int i=; i<n; i++)
if(P[i].t==) D[ ][num[]++ ] =i;
else if(P[i].t==) D[][ num[] ++ ]=i;
else D[][ num[]++ ]=i;
dp[n-][]=dp[n-][]=dp[n-][]=;
for(int i=n-; i>=;i--)dp[i][]=dp[i][]=dp[i][]=INF; for(int i=n-; i>=; i--)
{
if(P[i].t==)solve1(i);
else if(P[i].t==)solve2(i);
else solve3(i);
if(dp[i][]==INF)break;
}
for(int i=;i<m; i++)
{
int S1=INF,S2=INF;
int loc;
scanf("%d",&loc);
solve4(loc,S1,S2);
if(S1==INF){
printf("-1 -1\n");
}else{
printf("%d %d\n",S1,S2);
}
}
}
return ;
}
/*
386 20 1 1
2 369
351 */

F. Zublicanes and Mumocrates 树形dp

题意给了一棵树 要求使得这棵树所有的节点分为两个阵营,其中叶子节点要均分,求最少的两个阵营相邻, 也就是求 最少的边使得 这些边两头阵营不同

dp[cur][i][j] 表示当cur为i阵营的时候 有j个和i同阵营的方案

dp[cur][i][j+k] = min{dp[to][i^1][j=(叶子个数-d)]+dp[cur][i][k]+1,dp[to][i][j]+dp[cur][i][k]}

cnt为叶子节点的个数 最后答案是 min{ dp[root][0][cnt/2] ,dp[root][1][cnt/2]}

#include <algorithm>
#include <string.h>
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn=;
int H[maxn],to[maxn*],nx[maxn*],numofE;
void add(int u, int v)
{
numofE++;
to[numofE]=v;
nx[numofE]=H[u];
H[u]=numofE;
}
int dp[maxn][][maxn];
int dp2[][maxn],sz[maxn];
int d[maxn];
void dfs(int cur ,int per)
{
if(d[cur]==){
sz[cur]=;
dp[cur][][]=dp[cur][][]=;
return ;
}
dp[cur][][]=dp[cur][][]=;
for(int i=H[cur]; i ; i=nx[i])
{
int tto = to[i];
if(tto==per)continue;
dfs(tto,cur);
for(int i=; i<=sz[cur]; i++)
for(int u=; u<; u++)
{
if( dp[cur][u][i] == - ) continue; for(int j=; j<=sz[tto]; j++)
for(int v=; v<; v++)
{
if(dp[tto][v][j]==-)continue;
if(u==v)
{
if(dp2[u][i+j]==-)
{
int k=dp[cur][u][i]+dp[tto][v][j];
dp2[u][i+j] = k; }else {
int k=min(dp[cur][u][i]+dp[tto][v][j],dp2[u][i+j]);
dp2[u][i+j]=k; }
}else
{
int nu=sz[tto];
if(dp2[u][i+nu-j]==-)
{
int k=dp[cur][u][i]+dp[tto][v][j]+;
dp2[u][i+nu-j]=k;
}
else
{
int k=min(dp[cur][u][i]+dp[tto][v][j]+,dp2[u][i+nu-j]);
dp2[u][i+nu-j]=k; }
}
}
}
sz[cur]+=sz[tto];
for(int i=; i<=sz[cur]; i++)
for(int j=; j<; j++)
{
dp[cur][j][i]=dp2[j][i];
dp2[j][i]=-;
}
}
}
int main()
{
int n;
while(scanf("%d",&n)==)
{
memset(d,,sizeof(d));
memset(dp,-,sizeof(dp));
memset(sz,,sizeof(sz));
memset(dp2,-,sizeof(dp2));
memset(H,,sizeof(H));
numofE=;
for(int i=; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
d[a]++;d[b]++;
}
if(n==){
printf("%d\n",); continue;
}
int root;
int cnt=;
for(int i=; i<=n; i++){
if(d[i]==)cnt++;
else root=i;
}
dfs(root,-);
printf("%d\n",min(dp[root][][cnt/],dp[root][][cnt/]));
}
return ;
}
/*
6
1 2
2 5
2 3
3 4
3 6
*/

Codeforces Round #322 (Div. 2) E F的更多相关文章

  1. Codeforces Round #573 (Div. 1) 差F

    Codeforces Round #573 (Div. 1) E 题意:二维平面上有 n 个点,你可以放至多 m 条直线使得 (0,0) 与每个点的连线至少与一条直线相交.求原点与所有直线的距离最小值 ...

  2. Codeforces Round #322 (Div. 2) —— F. Zublicanes and Mumocrates

    It's election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The ...

  3. 树形dp - Codeforces Round #322 (Div. 2) F Zublicanes and Mumocrates

    Zublicanes and Mumocrates Problem's Link Mean: 给定一个无向图,需要把这个图分成两部分,使得两部分中边数为1的结点数量相等,最少需要去掉多少条边. ana ...

  4. Codeforces Round #322 (Div. 2) D. Three Logos 暴力

    D. Three Logos Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/problem ...

  5. Codeforces Round #322 (Div. 2) C. Developing Skills 优先队列

    C. Developing Skills Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/p ...

  6. Codeforces Round #322 (Div. 2) B. Luxurious Houses 水题

    B. Luxurious Houses Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/pr ...

  7. Codeforces Round #322 (Div. 2) A. Vasya the Hipster 水题

    A. Vasya the Hipster Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/581/p ...

  8. Codeforces Round #541 (Div. 2) (A~F)

    目录 Codeforces 1131 A.Sea Battle B.Draw! C.Birthday D.Gourmet choice(拓扑排序) E.String Multiplication(思路 ...

  9. Codeforces Round #532 (Div. 2):F. Ivan and Burgers(贪心+异或基)

    F. Ivan and Burgers 题目链接:https://codeforces.com/contest/1100/problem/F 题意: 给出n个数,然后有多个询问,每次回答询问所给出的区 ...

随机推荐

  1. 转:JAVA 的wait(), notify()与synchronized同步机制

    原文地址:http://blog.csdn.net/zyplus/article/details/6672775 转自:https://www.cnblogs.com/x_wukong/p/40097 ...

  2. 2018/05/02 PHP 之错误与异常处理

    在学习中,越学习越觉得自己基础薄弱. 在平常工作中,对于某些错误处理感觉不知道怎么下手,于是决定重新再整理一下. 强烈推荐这篇文章,真的感觉学习到了很多. 部分引用::再谈PHP错误与异常处理 -- ...

  3. linux关闭的时候出现异常: java.net.ConnectException: 拒绝连接 (Connection refused)

    这个时候: 需要先把java进程杀死. 然后再重新启动. 杀死进程: ps -aux | grep java 然后kill -9 进程 然后再重新启动.

  4. LEO原创-FMX之你不知道的ARC

    LEO原创13498714 FMX加入了ARC技术,对象创建后不用释放,FMX会帮你释放,是不是这样就不用关心对象的释放了呢,非也! 写简单的代码,这个功能也许很好用,但如果你写的是一个项目,那隐藏的 ...

  5. TensorFlow设置GPU占用量

    默认开启Tensorflow的session之后,就会占用几乎所有的显存,进行如下设置即可: 指定GPU编号: import os os.environ["CUDA_VISIBLE_DEVI ...

  6. LVS:三种负载均衡方式比较

    [转自http://soft.chinabyte.com/25/13169025.shtml] 1.什么是LVS? 首先简单介绍一下LVS (Linux Virtual Server)到底是什么东西, ...

  7. Hibernate的状态

    最新的Hibernate文档中为Hibernate对象定义了四种状态(原来是三种状态,面试的时候基本上问的也是三种状态),分别是:瞬时态(new, or transient).持久态(managed, ...

  8. what's the 单例模式

    what's the 单例模式 单例模式,是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例.即一个类只有一个对象实例 ...

  9. 006-网页嵌入数据Data URI scheme

    在项目css中或者图片展示中: url(data:image/png;base64,iVBORw0KGgoAAA 在RFC2397中定义的Data URI scheme,目的是将一些小的数据,直接嵌入 ...

  10. python-类属性和对象属性(转)

    class People(object): # 类属性是指定义在类的内部而且在方法的外部的属性 money = 10000 def __init__(self,name,age,gender=1): ...