• USACO18DEC Platinum


    standing out from the field 

    给你n个串,对于每个串求出只包含在这个串中的本质不同的子串?

    后缀自动机,建树,对于每一个点打上包含在哪个串中的标记。

    叶子都是前缀,直接在sam_build时预处理;其余的dfs一遍,由于x是son[x]的后缀,故x的状态由son[x]影响,如果son[x]有出现在不同串中的,标记x为-1。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=200005;
     5 char s[N+1];
     6 int last,sc,p,np,l[N],son[N][26],fa[N],cnt,head[N],f[N];
     7 ll ans[N]; 
     8 struct node{int to,next;}num[N];
     9 void add(int x,int y)
    10 {num[++cnt].to=y;num[cnt].next=head[x];head[x]=cnt;}
    11 void Sam(int c,int id)
    12 {
    13     p=last; np=last=++sc; l[np]=l[p]+1;
    14     for (;p&&!son[p][c];p=fa[p]) son[p][c]=np;
    15     if (!p) fa[np]=1;
    16     else {
    17         int q=son[p][c];
    18         if (l[p]+1==l[q]) fa[np]=q;
    19         else {
    20             int nq=++sc; l[nq]=l[p]+1;
    21             memcpy(son[nq],son[q],sizeof(son[q])); 
    22             fa[nq]=fa[q];fa[q]=fa[np]=nq;
    23             for (;son[p][c]==q;p=fa[p]) son[p][c]=nq;
    24         }
    25     }
    26     if (f[np]&&f[np]!=id) f[np]=-1;else f[np]=id;//处理叶子及一部分为前缀的非叶子 
    27 }
    28 void dfs(int x)
    29 {
    30     for (int i=head[x];i;i=num[i].next)
    31       if (num[i].to!=fa[x]) dfs(num[i].to);
    32     if (f[x]&&f[x]!=-1) ans[f[x]]+=l[x]-l[fa[x]];
    33    if (f[fa[x]]&&f[fa[x]]!=f[x]) f[fa[x]]=-1;else f[fa[x]]=f[x];
    34 }
    35 int main()
    36 {
    37     int T;scanf("%d",&T);
    38     sc=1;
    39     for (int i=1;i<=T;i++)
    40     {
    41         scanf("%s",s+1); int sl=strlen(s+1);
    42         last=1;
    43         for (int j=1;j<=sl;j++) Sam(s[j]-'a',i);
    44     }
    45     for (int i=2;i<=sc;i++) add(fa[i],i);
    46     dfs(1);
    47     for (int i=1;i<=T;i++) printf("%lld
    ",ans[i]);
    48    return 0;
    49 }
    View Code

    push a box

    f[x][y][dir]表示箱子在(x,y)格子,人是否可在箱子的dir方向。

    两种操作:推箱子,走人。“推箱子”可以用bfs处理,我们将箱子推过去的时候,必然有一个dir是可行的,“走人”就相当于是判断dir是否可以转换,具体地,从dir1的位置是否有一条不经过箱子所在点的路径走到dir2。tarjan点双,建成圆方树,存在路径当且仅当两个点的距离为2且经过一个方点。

    greedy gift takers

    每次在首位的人拿到礼物会排到倒数a[i]个人前。问无限次操作,有多少人获得礼物?n<=1e5。

    拿到礼物的人在原序列中一定是连续的一段。从封闭性的角度考虑,令a[i]=n-a[i],如果前缀M个人均有a[i]<=M,那么其他人一定不会拿到礼物。我们在前M个人中丢掉a[i]最大的一个,如果剩下的M-1个人的max_a[i]<=M-1,同理其他人拿不到礼物……具有二分性,每次如上check。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int read()
     4 {
     5    int x=0,f=1;char ch=getchar();
     6    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
     7    while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
     8    return x*f;
     9 }
    10 const int N=1e5+5;
    11 multiset<int,greater<int> > s;
    12 int l,r,n,a[N],ans;
    13 bool check(int x)
    14 {
    15     s.clear();
    16     for (int i=1;i<=x;i++) s.insert(a[i]);
    17     for (int i=x;i>=1;i--)
    18       if (*s.begin()<=i) return 1;
    19       else s.erase(s.begin());
    20     return 0;
    21 }
    22 int main()
    23 {
    24     n=read();
    25     for (int i=1;i<=n;i++) a[i]=n-read();
    26     l=1;r=n;
    27     while (l<=r)
    28     {
    29         int mid=(l+r)/2;
    30         if (check(mid)) ans=mid,r=mid-1;else l=mid+1;
    31     }
    32     printf("%d
    ",n-ans);
    33    return 0;
    34 }
    View Code
  • 相关阅读:
    Boost之使用篇(1)
    Lucene 3.0.0细节初窥(1)深入探索Lucene的consumer与processor
    整理一点关于Lucene的学习资料, 方便自己与别人查看
    使用Lucene 3.0.0的结构遍历TokenStream的内容.
    [原创]如何写一个完善的c++异常处理类
    Lucene 3.0.0 的TokenStream与Analyzer
    Lucene 3.0.0 之样例解析(4)IndexFiles.java
    贝叶斯、概率分布与机器学习
    Lucene用c++重写的详细安排
    Lucene 3.0.0的细节初窥(2)研究在索引过程中的缓存
  • 原文地址:https://www.cnblogs.com/Scx117/p/9216582.html
Copyright © 2020-2023  润新知