zoukankan      html  css  js  c++  java
  • bzoj4009 [HNOI2015]接水果

    【问题描述】

    风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果。由于她已经DT FC 了The big black,  她觉得这个游戏太简单了,于是发明了一个更加难的版本。首先有一个地图,是一棵由 n 个顶点、n-1 条边组成的树(例如图 1给出的树包含 8 个顶点、7 条边)。这颗树上有 P 个盘子,每个盘子实际上是一条路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值。第 i 个盘子就是顶点a_i到顶点b_i的路径(由于是树,所以从a_i到b_i的路径是唯一的),权值为c_i。接下来依次会有Q个水果掉下来,每个水果本质上也是一条路径,第i 个水果是从顶点 u_i 到顶点v_i 的路径。幽香每次需要选择一个盘子去接当前的水果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径(例如图1中从 3到7 的路径是从1到8的路径的子路径)。这里规定:从a 到b的路径与从b到 a的路径是同一条路径。当然为了提高难度,对于第 i 个水果,你需要选择能接住它的所有盘子中,权值第 k_i 小的那个盘子,每个盘子可重复使用(没有使用次数的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗?


    正解:扫描线+整体二分。

    这题竟然是权限题,真的操蛋。。给个链接算了,不想写题解了。。

    http://blog.csdn.net/thy_asdf/article/details/50363672

    话说我用树链剖分+树状数组这些小常数法宝都跑了0.4s是什么鬼。。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <complex>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <cstdio>
      8 #include <vector>
      9 #include <cmath>
     10 #include <queue>
     11 #include <stack>
     12 #include <map>
     13 #include <set>
     14 #define inf (1<<30)
     15 #define N (100010)
     16 #define il inline
     17 #define RG register
     18 #define ll long long
     19 #define lb(x) (x & -x)
     20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     21 
     22 using namespace std;
     23 
     24 struct plate{ int x1,x2,y1,y2,v; }p[2*N];
     25 struct fruit{ int x,y,k,id; }q[N],qu1[N],qu2[N];
     26 struct node{ int x,y,v; }rhl[N];
     27 struct edge{ int nt,to; }g[2*N];
     28 
     29 int head[N],top[N],fa[N],son[N],dep[N],pos[N],dfn[N],ed[N],sz[N],c[N],ans[N],n,P,Q,num,cnt,tot;
     30 
     31 il int gi(){
     32     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     33     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
     34 }
     35 
     36 il int cmpp(RG plate a,RG plate b){ return a.v<b.v; }
     37 
     38 il int cmpq(RG fruit a,RG fruit b){ return a.x<b.x; }
     39 
     40 il int cmpx(RG node a,RG node b){ return a.x<b.x; }
     41 
     42 il void add(RG int x,RG int v){ for (;x<=n;x+=lb(x)) c[x]+=v; return; }
     43 
     44 il int query(RG int x){ RG int res=0; for (;x;x-=lb(x)) res+=c[x]; return res; }
     45 
     46 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; }
     47 
     48 il void dfs1(RG int x,RG int p){
     49     fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG int v;
     50     for (RG int i=head[x];i;i=g[i].nt){
     51     v=g[i].to; if (v==p) continue;
     52     dfs1(v,x); sz[x]+=sz[v];
     53     if (sz[son[x]]<=sz[v]) son[x]=v;
     54     }
     55     return;
     56 }
     57 
     58 il void dfs2(RG int x,RG int p,RG int anc){
     59     top[x]=anc,dfn[x]=++cnt,pos[cnt]=x;
     60     if (son[x]) dfs2(son[x],x,anc); RG int v;
     61     for (RG int i=head[x];i;i=g[i].nt){
     62     v=g[i].to; if (v==p || v==son[x]) continue;
     63     dfs2(v,x,v);
     64     }
     65     ed[x]=cnt; return;
     66 }
     67 
     68 il int jump(RG int u,RG int v){
     69     RG int la=0;
     70     while (top[u]!=top[v]){
     71     if (dep[top[u]]<dep[top[v]]) swap(u,v);
     72     la=top[u],u=fa[top[u]];
     73     }
     74     if (dep[u]>dep[v]) swap(u,v);
     75     return u==v ? la : pos[dfn[u]+1];
     76 }
     77 
     78 il int lca(RG int u,RG int v){
     79     while (top[u]!=top[v]){
     80     if (dep[top[u]]<dep[top[v]]) swap(u,v);
     81     u=fa[top[u]];
     82     }
     83     return dep[u]<dep[v] ? u : v;
     84 }
     85 
     86 il void solve(RG int l,RG int r,RG int L,RG int R){
     87     if (L>R) return;
     88     if (l==r){
     89     for (RG int i=L;i<=R;++i) ans[q[i].id]=p[l].v;
     90     return;
     91     }
     92     RG int mid=(l+r)>>1,cnt=0,pos=0,tmp=0,t1=0,t2=0;
     93     for (RG int i=l;i<=mid;++i){
     94     rhl[++cnt]=(node){p[i].x1,p[i].y1,1};
     95     rhl[++cnt]=(node){p[i].x1,p[i].y2+1,-1};
     96     rhl[++cnt]=(node){p[i].x2+1,p[i].y1,-1};
     97     rhl[++cnt]=(node){p[i].x2+1,p[i].y2+1,1};
     98     }
     99     sort(rhl+1,rhl+cnt+1,cmpx);
    100     for (RG int i=L;i<=R;++i){
    101     while (pos<cnt && rhl[pos+1].x<=q[i].x) pos++,add(rhl[pos].y,rhl[pos].v);
    102     tmp=query(q[i].y); if (q[i].k<=tmp) qu1[++t1]=q[i]; else q[i].k-=tmp,qu2[++t2]=q[i];
    103     }
    104     while (pos<cnt) pos++,add(rhl[pos].y,rhl[pos].v);
    105     for (RG int i=L,j=1;i<=L+t1-1;++i,++j) q[i]=qu1[j];
    106     for (RG int i=L+t1,j=1;i<=R;++i,++j) q[i]=qu2[j];
    107     solve(l,mid,L,L+t1-1),solve(mid+1,r,L+t1,R); return;
    108 }
    109 
    110 il void work(){
    111     n=gi(),P=gi(),Q=gi(); RG int u,v,k;
    112     for (RG int i=1;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u);
    113     dfs1(1,0),dfs2(1,0,1);
    114     for (RG int i=1;i<=P;++i){
    115     u=gi(),v=gi(),k=gi();
    116     if (dfn[u]>dfn[v]) swap(u,v); RG int Lca=lca(u,v);
    117     if (Lca!=u) p[++tot]=(plate){dfn[u],ed[u],dfn[v],ed[v],k};
    118     else{
    119         RG int w=jump(u,v);
    120         if (dfn[w]>1) p[++tot]=(plate){1,dfn[w]-1,dfn[v],ed[v],k};
    121         if (ed[w]<n) p[++tot]=(plate){dfn[v],ed[v],ed[w]+1,n,k};
    122     }
    123     }
    124     for (RG int i=1;i<=Q;++i){
    125     u=gi(),v=gi(),k=gi(); if (dfn[u]>dfn[v]) swap(u,v);
    126     q[i]=(fruit){dfn[u],dfn[v],k,i};
    127     }
    128     sort(p+1,p+tot+1,cmpp),sort(q+1,q+Q+1,cmpq),solve(1,tot,1,Q);
    129     for (RG int i=1;i<=Q;++i) printf("%d
    ",ans[i]); return;
    130 }
    131 
    132 int main(){
    133     File("fruit");
    134     work();
    135     return 0;
    136 }
  • 相关阅读:
    如何提高AJAX客户端响应速度
    JS 数组间的操作
    Spring上传报错413
    设计模式-简单工厂模式学习笔记
    vue辅助函数mapStates与mapGetters
    Vue编程式跳转
    Vue父子,子父,非父子组件之间传值
    node.js中的fs.rename()方法
    map字典,储存cookie,切换账户,展示购物车不同商品
    Gulp
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6526705.html
Copyright © 2011-2022 走看看