发现这跟\(Gold\)难度简直天差地别啊。。

\(T1\)

传送门

解题思路

  这道题还是很可做的,发现题意可以传化成一棵树每次从叶子节点删边,然后有\(m\)条限制,形如\(a\)在\(b\)前面删去。发现\(a\)在\(b\)前面删去其实就是\(ban\)掉一棵树上一段或两段连续的\(dfs\)序,这个讨论一下关系即可。这样就可以树剖+线段树维护,但是直接做只有\(88\)分,因为没有考虑不合法的情况,判不合法的情况可以根据删除关系建一张有向图,然后最后判断有无环即可。

代码

#include<bits/stdc++.h>

using namespace std;
const int N=100005; inline int rd(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
} int n,m,num,siz[N],top[N],son[N],id[N],fa[N],dep[N],f[N][20];
int vis[N],tot;
bool use[N],tt[N];
vector<int> v[N],G[N]; struct Segment_Tree{
#define mid ((l+r)>>1)
int sum[N<<2],tag[N<<2];
void pushdown(int x){
sum[x<<1]|=tag[x];
sum[x<<1|1]|=tag[x];
tag[x<<1]|=tag[x];
tag[x<<1|1]|=tag[x];
tag[x]=0;
}
void update(int x,int l,int r,int L,int R){
if(L>R) return ;
if(L<=l && r<=R) {sum[x]=tag[x]=1; return;}
if(tag[x]) pushdown(x);
if(L<=mid) update(x<<1,l,mid,L,R);
if(mid<R) update(x<<1|1,mid+1,r,L,R);
sum[x]=(sum[x<<1]|sum[x<<1|1]);
}
int query(int x,int l,int r,int pos){
if(l==r) return sum[x];
if(tag[x]) pushdown(x);
if(pos<=mid) return query(x<<1,l,mid,pos);
return query(x<<1|1,mid+1,r,pos);
}
#undef mid
}tree; void dfs1(int x,int F){
siz[x]=1; fa[x]=F; int maxson=-1;
f[x][0]=F;
for(int i=1;i<=17;i++)
f[x][i]=f[f[x][i-1]][i-1];
for(int i=0;i<v[x].size();i++){
int u=v[x][i]; if(u==F) continue;
dep[u]=dep[x]+1; dfs1(u,x); siz[x]+=siz[u];
if(siz[u]>maxson) maxson=siz[u],son[x]=u;
}
} void dfs2(int x,int topf){
top[x]=topf; id[x]=++num;
if(!son[x]) return;
dfs2(son[x],topf); int u;
for(int i=0;i<v[x].size();i++){
u=v[x][i]; if(u==fa[x] || u==son[x]) continue;
dfs2(u,u);
}
} int jump(int x,int D){
for(int i=17;~i;i--)
if(dep[f[x][i]]>=D) x=f[x][i];
return x;
} void dfs(int x,int F){
use[x]=1;
for(int i=0;i<v[x].size();i++){
int u=v[x][i]; if(u==F || use[u]) continue;
// cout<<u<<" "<<x<<endl;
G[u].push_back(x); dfs(u,x);
}
} void cir(){
for(int i=1;i<=n;i++) puts("0");
exit(0);
} void find_cir(int x){
for(int i=0;i<G[x].size();++i){
int u=G[x][i];
if(vis[u]) cir();
if(tt[u]) continue;
vis[u]=1; tt[u]=1;
find_cir(u); vis[u]=0;
}
} int main(){
// freopen("in","r",stdin);
n=rd(),m=rd(); int x,y;
for(int i=1;i<n;i++){
x=rd(),y=rd();
v[x].push_back(y);
v[y].push_back(x);
}
dfs1(1,0); dfs2(1,1);
while(m--){
x=rd(),y=rd(); G[x].push_back(y);
// cout<<x<<" "<<y<<endl;
if(id[y]>=id[x] && id[y]<=id[x]+siz[x]-1){
int now=jump(y,dep[x]+1);
tree.update(1,1,n,1,id[now]-1);
tree.update(1,1,n,id[now]+siz[now],n);
G[x].push_back(now);
// cout<<x<<" "<<now<<endl;
for(int i=0;i<v[x].size();i++){
int u=v[x][i];
if(id[u]>=id[now] && id[u]<=id[now]+siz[now]-1) continue;
// cout<<u<<" "<<x<<endl;
G[u].push_back(x); dfs(u,x);
}
}
else{
tree.update(1,1,n,id[x],id[x]+siz[x]-1);
dfs(x,fa[x]);
}
}
for(int i=1;i<=n;i++)
if(!tt[i]) find_cir(i);
for(int i=1;i<=n;i++) {
if(!tree.query(1,1,n,id[i])) puts("1");
else puts("0");
}
return 0;
}


\(T3\)

传送门

解题思路

  神仙题。首先发现对于一个点来说它的答案一定是从自己这个点直接跳下去或者向左右两边分别找到一个点跳下去。考虑区间\([0,L]\),设\(x\)走到\(L\)的概率为\(f(x)\),那么有\(f(x)=\frac{f(x-1)+f(x+1)}{2}\),发现这是个等差数列的形式,又因为\(f(L)=1,f(0)=0\)可以解得\(f(x)=\frac{x}{L}\),那么这个人在某个点往左右两边走时左边到达\(a\)点,右边到达\(b\)点,则他获得的收益为\(V_a \frac{b-i}{b-a}+V_b \frac{i-a}{b-a}\),那么就得到一个暴力的做法,就是枚举左右端点算最大值。但发现这样复杂度太高,考虑如何能快速找到左右两点。如果把它们放到平面直角坐标系上,每个点横坐标设为位置,纵坐标设为该位置的权值。那么画个图带进去可以发现,要求的其实就是两点连线与\(x=i\)之间交点的纵坐标,那么确定这两个点就可以用凸包判断了。就是把凸包找出来,然后对于一个点来说如果它在凸包上,答案就为这个点的纵坐标,否则为它前后两个凸包上的点连线的\(x=i\)时的纵坐标。

代码

#include<bits/stdc++.h>

using namespace std;
const int N=100005;
const double eps=1e-8;
typedef long long LL; int n,stk[N],top;
double a[N]; struct Node{
int x; LL y;
Node(int _x=0,LL _y=0){
x=_x; y=_y;
}
}node[N]; Node operator-(Node A,Node B){
return Node(A.x-B.x,A.y-B.y);
}
inline LL cross(Node A,Node B){
return A.x*B.y-A.y*B.x;
} inline bool check(int x,int y,int z){
return cross((node[y]-node[x]),(node[z]-node[y]))>=eps;
} inline LL calc(int x,int y,int z){
return (node[y].y*(node[z].x-node[x].x)+node[x].y*(node[y].x-node[z].x))/(node[y].x-node[x].x);
} int main(){
scanf("%d",&n); double tmp;
for(int i=1;i<=n;i++) {
node[i].x=i; scanf("%lf",&tmp);
node[i].y=tmp*100000;
}
stk[++top]=0; node[n+1].x=n+1;
for(int i=1;i<=n+1;i++){
while(top>1 && check(stk[top-1],stk[top],i)) top--;
stk[++top]=i;
} int now=1;
for(int i=1;i<=n;i++){
while(stk[now]<i) now++;
if(stk[now]==i) printf("%lld\n",(LL)(node[i].y));
else printf("%lld\n",calc(stk[now-1],stk[now],i));
}
return 0;
}


USACO2018 DEC(Platinum) (树上乱搞,期望+凸包)的更多相关文章

  1. zoj 3820 Building Fire Stations(树上乱搞)

    做同步赛的时候想偏了,状态总是时好时坏.这状态去区域赛果断得GG了. 题目大意:给一棵树.让求出树上两个点,使得别的点到两个点较近的点的距离最大值最小. 赛后用O(n)的算法搞了搞,事实上这道题不算难 ...

  2. BZOJ3573: [Hnoi2014]米特运输(树上乱搞)

    Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1669  Solved: 1031[Submit][Status][Discuss] Descript ...

  3. CF809E Surprise me!(莫比乌斯反演+Dp(乱搞?))

    题目大意: 给你一棵树,树上的点编号为\(1-n\).选两个点\(i.j\),能得到的得分是\(\phi(a_i*a_j)*dis(i,j)\),其中\(dis(i,j)\)表示\(a\)到\(b\) ...

  4. BZOJ4401:块的计数(乱搞)

    Description 小Y最近从同学那里听说了一个十分牛B的高级数据结构——块状树.听说这种数据结构能在sqrt(N)的时间内维护树上的各种信息,十分的高效.当然,无聊的小Y对这种事情毫无兴趣,只是 ...

  5. 洛谷P5211 [ZJOI2017]字符串(线段树+乱搞)

    题面 传送门 题解 为什么大佬们全都是乱搞的--莫非这就是传说中的暴力能进队,乱搞能AC-- 似乎有位大佬能有纯暴力+玄学优化\(AC\)(不算上\(uoj\)的\(Hack\)数据的话--这要是放到 ...

  6. bzoj 1050: [HAOI2006]旅行comf(codevs.cn 1001 舒适的路线) 快排+并查集乱搞

    没用的话:好像很久没发博客了,主要是懒太蒟找不到水题.我绝对没弃坑...^_^ 还用些话:本文为博主原创文章,若转载请注明原网址和作者. 进入正题: 先pa网址: bzoj :http://www.l ...

  7. BZOJ_2801_[Poi2012]Minimalist Security_dfs树+特判+乱搞

    BZOJ_2801_[Poi2012]Minimalist Security_dfs树+特判+乱搞 Description 给出一个N个顶点.M条边的无向图,边(u,v)有权值w(u,v),顶点i也有 ...

  8. VIJOS1476 旅行规划(树形Dp + DFS暴力乱搞)

    题意: 给出一个树,树上每一条边的边权为 1,求树上所有最长链的点集并. 细节: 可能存在多条最长链!最长链!最长链!重要的事情说三遍 分析: 方法round 1:暴力乱搞Q A Q,边权为正-> ...

  9. [bzoj4796][CERC2016]Key Knocking_乱搞

    Key Knocking bzoj-4796 CERC-2016 题目大意:描述没有题面短系列..题目链接 注释:$1\le n\le 10^5$. 想法: 乱搞稳AC.考试的时候调试信息又一次杀死了 ...

随机推荐

  1. ant buid.xml 模板

    <?xml version="1.0" encoding="UTF-8"?> <project name="ant" de ...

  2. [19/06/04-星期二] HTML基础_实体(转义字符)、图片标签(img)、元标签(meta)、语法规范、内联框架(iframe)、超链接

    一.实体(转义字符) 在HTML中,一些诸如<.> 就是普通的小于号和大于号不能直接使用,因为浏览可能会把它当成一个标签去解析,所以需要一些特殊字符去表示这些特殊字符, 这些字符我们称他们 ...

  3. MySQL-快速入门(8)存储过程、存储函数

    1.存储过程 1>创建存储过程:create procedure create procedure sp_name ([in | out | inout] param_name type) [c ...

  4. 安装配置php及fastadmin

    FastAdmin教程之准备运行环境   一.Node.js http://nodejs.cn/download/ https://npm.taobao.org/mirrors/node/v8.4.0 ...

  5. 如何通过PHP将excel的数据导入MySQL中

    在开发PHP程序时,很多时候我们会有将数据批量导入数据库的需求,如学生信息批量添加到数据库中,而事先用excel编排好,对excel实行操作,便是我们比较常用的选择方式. 在对excel的操作中,ph ...

  6. asp,net 传值方式 优缺点比较

    .net C#中页面之间传值传参的六种方法 1.QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用 ...

  7. C++实现简单的日志记录

    C++实现简单的日志记录 //dlogger.h #ifndef DLOGGER_H #define DLOGGER_H #include <iostream> #include < ...

  8. 关于express 连接 mongodb数据库报错

    关于express 连接 mongodb数据库报错 nodejs DeprecationWarning: current URL string parser is deprecated, and wi ...

  9. 可视化缺失值的办法——R语言

    在数据分析中,对缺失值的处理是很关键一步,一般用summary()函数 a<-c(,,,NA) B<-c("a","b","c" ...

  10. Insomni'hack teaser 2019 - Reverse - beginner_reverse

    参考链接 https://ctftime.org/task/7455 题目描述 A babyrust to become a hardcore reverser 点我下载 解题过程 一道用rust写的 ...