zoukankan      html  css  js  c++  java
  • BZOJ3681: Arietta

    题解:

    数据结构来优化网络流,貌似都是用一段区间来表示一个点,然后各种乱搞。。。

    发现主席树好吊。。。在树上建主席树貌似有三种方法:

    1.建每个点到根节点这条链上的主席树,可以回答和两点间的路径的XX问题。

    2.按DFS序然后就成了序列上的主席树,可以回答子树第k大等XX问题。

    3.先给每个点单独建立主席树,然后dfs下去,并且将一个点的所有子树合并起来,相当于新建了n棵主席树,但这样可以解决该题。。。

    神犇勿喷。。。

    因为这样从rt[x]查询到的区间就可以直接表示满足题意的点了,然后就是最大流了。

    代码:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<iostream>
      7 #include<vector>
      8 #include<map>
      9 #include<set>
     10 #include<queue>
     11 #include<string>
     12 #define inf 1000000000
     13 #define maxn 100000+5
     14 #define maxm 1000000+5
     15 #define eps 1e-10
     16 #define ll long long
     17 #define pa pair<int,int>
     18 #define for0(i,n) for(int i=0;i<=(n);i++)
     19 #define for1(i,n) for(int i=1;i<=(n);i++)
     20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
     23 #define mod 1000000007
     24 #define mid ((l+r)>>1)
     25 using namespace std;
     26 inline int read()
     27 {
     28     int x=0,f=1;char ch=getchar();
     29     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     30     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     31     return x*f;
     32 }
     33 int  n,m,s,t,cnt,maxflow,tot=1,head[maxm],cur[maxm],h[maxm];
     34 queue<int>q;
     35 int rt[maxn],lc[maxm],rc[maxm];
     36 struct edge{int go,next,v;}e[maxm];
     37 vector<int> son[maxn];
     38 inline void add(int x,int y,int v)
     39 {
     40     e[++tot]=(edge){y,head[x],v};head[x]=tot;
     41     e[++tot]=(edge){x,head[y],0};head[y]=tot;
     42 }
     43 bool bfs()
     44 {
     45     for(int i=0;i<=cnt;i++)h[i]=-1;
     46     q.push(s);h[s]=0;
     47     while(!q.empty())
     48     {
     49         int x=q.front();q.pop();
     50         for(int i=head[x];i;i=e[i].next)
     51          if(e[i].v&&h[e[i].go]==-1)
     52          {
     53             h[e[i].go]=h[x]+1;q.push(e[i].go);
     54          }
     55     }
     56     return h[t]!=-1;
     57 }
     58 int dfs(int x,int f)
     59 {
     60     if(x==t) return f;
     61     int tmp,used=0;
     62     for(int i=cur[x];i;i=e[i].next)
     63      if(e[i].v&&h[e[i].go]==h[x]+1)
     64     {
     65         tmp=dfs(e[i].go,min(e[i].v,f-used));
     66         e[i].v-=tmp;if(e[i].v)cur[x]=i;
     67         e[i^1].v+=tmp;used+=tmp;
     68         if(used==f)return f;       
     69     }
     70     if(!used) h[x]=-1;
     71     return used;
     72 }
     73 void dinic()
     74 {
     75     maxflow=0;
     76     while(bfs())
     77     {
     78         for (int i=0;i<=cnt;i++)cur[i]=head[i];maxflow+=dfs(s,inf);
     79     }
     80 }
     81 inline void insert(int x)
     82 {
     83     int l,r;
     84     for(l=1,r=n,++cnt;l<r;++cnt)
     85      if(x<=mid)
     86      {
     87          add(cnt,lc[cnt]=cnt+1,inf);
     88          r=mid;
     89      }else
     90      {
     91          add(cnt,rc[cnt]=cnt+1,inf);
     92          l=mid+1;
     93      } 
     94     add(cnt,t,1);
     95 }
     96 inline int merge(int x,int y,int l,int r)
     97 {
     98     if(x*y==0)return x+y;
     99     int k=++cnt;
    100     if(l==r)add(k,x,inf),add(k,y,inf);
    101     else
    102     {
    103         add(k,lc[k]=merge(lc[x],lc[y],l,mid),inf);
    104         add(k,rc[k]=merge(rc[x],rc[y],mid+1,r),inf);
    105     }
    106     return k;
    107 }
    108 inline void dfs(int x)
    109 {
    110     if(!son[x].size())return;
    111     for(int i=son[x].size()-1;~i;i--)
    112      {
    113       dfs(son[x][i]);
    114       rt[x]=merge(rt[x],rt[son[x][i]],1,n);
    115      } 
    116 }
    117 inline void query(int k,int l,int r,int x,int y)
    118 {
    119     if(!k)return;
    120     if(l==x&&r==y){add(cnt,k,inf);return;}
    121     if(y<=mid)query(lc[k],l,mid,x,y);
    122     else if(x>mid)query(rc[k],mid+1,r,x,y);
    123     else query(lc[k],l,mid,x,mid),query(rc[k],mid+1,r,mid+1,y);
    124 }
    125 int main()
    126 {
    127     freopen("input.txt","r",stdin);
    128     freopen("output.txt","w",stdout);
    129     n=read();m=read();s=0;t=1;cnt=t;
    130     for2(i,2,n)son[read()].push_back(i);
    131     for1(i,n)rt[i]=cnt+1,insert(read());
    132     dfs(1);
    133     while(m--)
    134     {
    135         int l=read(),r=read(),x=read(),y=read();
    136         add(s,++cnt,y);
    137         query(rt[x],1,n,l,r);
    138     }
    139     dinic();
    140     cout<<maxflow<<endl;
    141     return 0;
    142 }
    View Code

    3681: Arietta

    Time Limit: 20 Sec  Memory Limit: 64 MB
    Submit: 64  Solved: 28
    [Submit][Status]

    Description

    Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中。
    但是她从未停止过和恋人 Velding 的书信往来。一天,她准备去探访他。
    对着窗外的阳光,临行前她再次弹起了琴。
    她的琴的发声十分特殊。
    让我们给一个形式化的定义吧。
    所有的 n 个音符形成一棵由音符 C ( 1 号节点) 构成的有根树,每一个音符有一个音高 Hi 。
    Arietta 有 m 个力度,第 i 个力度能弹出 Di 节点的子树中,音高在 [Li,Ri] 中的任意一个音符。
    为了乐曲的和谐,Arietta 最多会弹奏第 i 个力度 Ti 次。
    Arietta 想知道她最多能弹出多少个音符。

    Input

    输入共 m + 3 行。
    第一行两个整数 n, m ,意义如题目所述。
    第二行 n - 1 个整数 Pi ,表示节点 i ( i = 2 . . . n ) 的父亲节点的编号。
    第三行 n 个整数 Hi 。
    接下来的 m 行,每行四个整数 Li,Ri,D,Ti

    Output


    输出一个整数表示 Arietta 最多能弹奏多少音符。
    数据范围与约定
    对于 100% 的数据,1 ≤ n, m ≤ 10000 。
    对于所有数据,1 ≤ Hi , Ti , Pi ≤ n, 1 ≤ Li ≤ Ri ≤ n 。

    Sample Input

    5 2
    1 1 2 2
    5 3 2 4 1
    1 3 2 1
    3 5 1 4

    Sample Output

    4

    HINT

    第一个力度弹奏音符5,第二个力度弹奏音符1,2,4。


    数据范围与约定

    对于 100% 的数据,1 ≤ n, m ≤ 10000 。

    对于所有数据1<=Hi,Ti,Pi<=N,1<=Li<=Ri<=N

     

     

    Source

  • 相关阅读:
    随笔
    随笔
    第一个存储过程
    mysql 存储过程
    join
    随笔
    玩家注册登录
    mysql 存储二进制数据
    mysql学习
    socket listen/accept
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4197839.html
Copyright © 2011-2022 走看看