zoukankan      html  css  js  c++  java
  • 日常小测3.7

    T1:给定一棵以1号点为根的树,每条边上有字母。定义一个节点的串为该节点走到根节点的路径字符。给定若干个询问,每次询问给定一个点集,询问这若干个点两两之间的lcp总和。

    真心对字符串的题不感冒啊。我们考虑构建广义自动机。为什么呢,我们先考虑一个弱智版题目,如果给你一个trie,然后做同样的事情,那么我们完全可以建一个虚树,然后对于每一个节点贡献就是一个关于子树大小的很好求的东西。构建广义后缀自动机之后的parent树其实就是这么一个压缩了一些的trie。然后我们就可以做啦。

    由于虚树没写过,SAM有一段时间没写过了,感觉很难写的样子。所以暂(yong)时(yuan)不写了。

    T2:给定一棵完全二叉树,每个节点可以容纳xi个东西,给定一个大小为n的点集(里面的点可以重复),分别求对于每一个k(1<=k<=n),这n个点前k个点全部被容纳的代价。容纳代价为这个节点原先的位置到它被容纳节点的距离。

    首先很容易得到一个最小费用流算法。但是这还不够,因为我们没有用到一个很重要的,一看就知道最终复杂度是nlogn的条件:完全二叉树。那么肯定是树高大有文章。我们考虑每次费用流,如果我们把源点和汇点去掉的话,然后每一条边是树边的话,每次费用流复杂度就是n的。这还不够,我们发现树高很小,那么我们用树形dp来维护这个费用流的边,每次跑完之后logn更新一下,总复杂度就是nlogn了。

    每个节点我们维护一个pair,表示它子树里离它最近的点的距离是多少,这个点是什么。还维护了一个r数组。这特别关键,我们用它来记录这个点的反向边。我们定义向上爬为正方向,向下那就是反向边了。每次爬树高dp的时候我们要考虑反向边的存在,加加减减就好了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 #define N 100005
     5 #define INF 1e9
     6 inline LL read(){
     7        LL x=0,f=1; char a=getchar();
     8        while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();}
     9        while(a>='0' && a<='9') x=x*10+a-'0',a=getchar();
    10        return x*f;
    11 }
    12 int n,m,c[N],p[N],r[N];
    13 LL ans;
    14 struct dp{
    15     int dep,num;
    16     bool operator < (const dp& w)const{
    17         return dep<w.dep;
    18     }
    19 }f[N];
    20 dp operator + (const dp& a,const int& b){
    21     return (dp){a.dep+b,a.num};
    22 }
    23 inline void update(int x){
    24     if(c[x]) f[x]=(dp){0,x}; else f[x]=(dp){INF,0}; 
    25     if((x<<1)<=n) f[x]=min(f[x],f[x<<1]+(r[x<<1]>=0?1:-1));
    26     if((x<<1|1)<=n) f[x]=min(f[x],f[x<<1|1]+(r[x<<1|1]>=0?1:-1));
    27 }
    28 int main(){
    29     n=read(); m=read();
    30     for(int i=1;i<=n;i++) c[i]=read();
    31     for(int i=1;i<=m;i++) p[i]=read();
    32     for(int i=n;i;i--) update(i);
    33     for(int x,y,i=1;i<=m;i++){
    34         x=p[i];
    35         dp mn=(dp){INF,0}; int t=0;
    36         while(x) mn=min(mn,f[x]+(t)),t+=(r[x]<=0?1:-1),x>>=1;
    37         x=p[i]; y=mn.num; c[y]--;
    38         while(x!=y){
    39             if(x>y) r[x]--,update(x),x>>=1;
    40             else r[y]++,update(y),y>>=1;
    41         }
    42         while(x) update(x),x>>=1;
    43         ans+=mn.dep;
    44         printf("%lld ",ans);
    45     }
    46     return 0;
    47 }

    T3:KD_tree板题,第一次写KD_tree

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 #define N 400005
     5 #define INF  1e9
     6 inline LL read(){
     7        LL x=0,f=1; char a=getchar();
     8        while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();}
     9        while(a>='0' && a<='9') x=x*10+a-'0',a=getchar();
    10        return x*f;
    11 }
    12 int n,cnt,num[N],pos[N],root,ans,tmp;
    13 struct point{
    14     int x,y,a,b,id;
    15     inline void get(){
    16         x=read(); y=read(); a=read(); b=read();
    17     }
    18     bool operator < (const point& w)const{
    19         if(x==w.x) return y<w.y;
    20         return x<w.x;
    21     }
    22 }p[N];
    23 inline bool cmp(int x,int y){
    24     return p[x]<p[y];
    25 }
    26 struct KD_tree{
    27     int xl,xr,yb,yt,l,r;
    28     int son[2],mx,kind;
    29     inline void init(){
    30         xl=INF; xr=0; yb=INF; yt=0;
    31     }
    32 }a[N];
    33 inline bool cmpx(const point& a,const point& b){return a.x<b.x;}
    34 inline bool cmpy(const point& a,const point& b){return a.y<b.y;}
    35 inline void update(int k){a[k].mx=max(a[a[k].son[0]].mx,a[a[k].son[1]].mx);}
    36 void build(int& k,int l,int r){
    37     k=++cnt; a[k].l=l; a[k].r=r;
    38     int F,mid=(l+r)>>1;
    39     a[k].init();
    40     for(int i=l;i<=r;i++){
    41         a[k].xl=min(a[k].xl,p[i].x);
    42         a[k].xr=max(a[k].xr,p[i].x);
    43         a[k].yb=min(a[k].yb,p[i].y);
    44         a[k].yt=max(a[k].yt,p[i].y);
    45     }
    46     if(l==r) return;
    47     a[k].kind=F=a[k].xr-a[k].xl>a[k].yt-a[k].yb?0:1;
    48     if(!F) nth_element(p+l,p+mid,p+r+1,cmpx);
    49     else nth_element(p+l,p+mid,p+r+1,cmpy);
    50     build(a[k].son[0],l,mid); build(a[k].son[1],mid+1,r);
    51     update(k);
    52 }
    53 void modify(int k,int x,int val){
    54     if(a[k].l==a[k].r) a[k].mx=val;
    55     else{
    56         int F=(x<=(a[k].l+a[k].r)/2?0:1);
    57         modify(a[k].son[F],x,val);
    58         update(k);
    59     }
    60 }
    61 int query(int k,int xl,int xr,int yb,int yt){
    62     if(a[k].yt<yb || a[k].yb>yt || a[k].xl>xr || a[k].xr<xl) return 0;
    63     if(a[k].yt<=yt && a[k].yb>=yb && a[k].xl>=xl && a[k].xr<=xr) return a[k].mx;
    64     int ret=0,F=(a[a[k].son[0]].mx>a[a[k].son[1]].mx?0:1); //优化 
    65     ret=query(a[k].son[F],xl,xr,yb,yt);
    66     if(ret<a[a[k].son[F^1]].mx) ret=max(ret,query(a[k].son[F^1],xl,xr,yb,yt));
    67     return ret;
    68 }
    69 int main(){
    70     n=read();
    71     for(int i=1;i<=n;i++) num[i]=i,p[i].id=i,p[i].get();
    72     sort(num+1,num+1+n,cmp);
    73     build(root,1,n);
    74     for(int i=1;i<=n;i++) pos[p[i].id]=i;
    75     for(int x,i=n;i;i--){
    76         x=pos[num[i]];
    77         tmp=query(root,p[x].x,p[x].a,p[x].y,p[x].b)+1;
    78         ans=max(ans,tmp);
    79         modify(root,x,tmp);
    80     }
    81     printf("%d
    ",ans);
    82     return 0;
    83 }
  • 相关阅读:
    统计候选人
    九宫格输入法
    前端同学面试准备
    1、单元格内换行诀窍、合并单元格、身份证、日期乱码
    读写锁
    混合锁、互斥锁
    原子操作、自旋锁
    pipeline httpmodule
    vm +cenos7+gitlab 02
    vm +cenos7+gitlab 01
  • 原文地址:https://www.cnblogs.com/enigma-aw/p/6514626.html
Copyright © 2011-2022 走看看