集训Day1

雅礼集训2017Day1的题

感觉上不可做实际上还挺简单的吧

T1

区间加 区间除法向下取整

查询区间和 区间最小值

大力上线段树,把除法标记推到底,加法标记就是按照线段树的来

先拿30

然后60的数据随机不知道该怎么做

开始YY

那个“向下取整”的tag并不能累加

所以考虑转化

除法->减法

如果一个区间要减的都是一样的数,直接减就行了,如果不一样,就递归下去,反正1个数肯定减的是一样的

本来想拿60,结果A了

 

T2

n*n的棋盘(n = 1000)每次把找一行,把它的颜色序列copy下来涂到一列上

问最少多少次能把整个棋盘涂黑

首先 全白肯定无解

其次 只要把一行涂黑 之后涂n次就可以了

然后 大力模拟发现并没有比这个优的策略

于是一顿乱搞

我们枚举第i行,假装要把他弄成全1的。

设第i行的0的数量为cc[i],那么考虑第i列是否含有1,如果含有1那么就可以用含有1的那列的那行给第i行所有0的地方赋值,需要cc[i]步。

如果第i列不含有1,我们要花1次操作给第i列搞个1出来,所以答案是cc[i]+1步。

每行取个min

听说是签到题...数据极水 被各种对的不对的做法爆切

 

T3

w 为两字符串,定义:

  1. $w[l,r]$  表示字符串 $w$ 在区间 $[l,r]$中的子串;
  2. $w$ 在 $s $中出现的频率定义为$w$ 在 $s$  中出现的次数;
  3. $f(s,w,l,r)$表示 $w[l,r]$ 在 $s$ 中出现的频率。

比如 $f(ababa,aba,1,3)=2$。

现在给定串 $s$,$m$个区间 $[l,r] $ 和长度 $k$ ,你要回答 $q$  个询问,每个询问给你一个长度为 $k$  的字符串 $w$  和两个整数 $a,b$,求:

$\sum\limits_{i = a} ^ b f(s, w, l_i, r_i)$

重要条件

$\sum w_i$ 是个定值

所以很eazy看了题解后想到要写两种做法

首先考虑k小的情况

这种情况我们可以用SAM暴力处理出right集合计算每一个子串在当前串出现的次数

我的暴力永远比别人慢系列

用莫队可以把O(n^2 k ^2)优化到(n sqrt n k ^2)写写写 

 

k大时可以考虑在SAM的parent树上跑一个倍增

暴力记前缀然后倍增往上跳找到后缀

这样遍历每个子串就可以做了

 

这是什么完全不可做的毒瘤题啊妈妈带我回家吧我不学OI了

嗯 抬头 微笑

 

感觉没看到签到题有点亏...想T1想了2个小时有点不应该

然后1个小时迅速切T2

T3就没时间想了只能n^3的KMP

最后100 + 100 + 30

感觉拿了个大众分?

 

2018.6.6upd

代码写完了 贴一下

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);x = 10 * x + ch - '0',ch = getchar());
    return x * f; 
}
inline LL Lread()
{
    LL x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);x = 10 * x + ch - '0',ch = getchar());
    return x * f; 
}
const int maxn = 1e5 + 10;
int n,m;
LL a[maxn];
LL minx[maxn << 2],sum[maxn << 2],maxx[maxn << 2],add[maxn << 2];
#define ls (x << 1)
#define rs ((x << 1) | 1)
inline void pushup(int x){minx[x] = min(minx[ls],minx[rs]);sum[x] = sum[ls] + sum[rs];maxx[x] = max(maxx[ls],maxx[rs]);}
inline void pushdown(int x,int l,int r)
{
    if(add[x])
    {
        add[ls] += add[x];add[rs] += add[x];
        int mid = (l + r) >> 1; 
        sum[ls] += add[x] * (mid - l + 1);sum[rs] += add[x] * (r - mid);
        minx[ls] += add[x];minx[rs] += add[x];maxx[ls] += add[x];maxx[rs] += add[x];
        add[x] = 0;
    }
}
inline void build(int x,int l,int r)
{
    if(l == r)
    {
           maxx[x] = minx[x] = sum[x] = a[l];
           return;
    }
    add[x] = 0;
    int mid = (l + r) >> 1;
    build(ls,l,mid);build(rs,mid + 1,r);
    pushup(x);
}
inline void update1(int x,int l,int r,int L,int R,int c) //Add
{
    if(L <= l && r <= R)
    {
           add[x] += c;
           sum[x] += (r - l + 1) * c;
           minx[x] += c;maxx[x] += c;
           return;
    }
    pushdown(x,l,r);int mid = (l + r) >> 1;
    if(L <= mid)update1(ls,l,mid,L,R,c);
    if(R > mid)update1(rs,mid + 1,r,L,R,c);
    pushup(x);
}
inline void update2(int x,int l,int r,int L,int R,int d) //Div
{
    if(L <= l && r <= R)
    {
        if(minx[x] == maxx[x] || ((maxx[x] % d == 0) && (maxx[x] - 1 == minx[x])))
        {
            LL delta = maxx[x] - (LL)floor((1.0 * maxx[x] / d));
            add[x] -= delta;
            minx[x] -= delta;maxx[x] -= delta;
            sum[x] -= 1LL *delta * (r - l + 1);
            return;
        }
        //return;
    }
    pushdown(x,l,r);int mid = (l + r) >> 1;
    if(L <= mid)update2(ls,l,mid,L,R,d);
    if(R > mid)update2(rs,mid + 1,r,L,R,d);
    pushup(x);
}
inline LL query1(int x,int l,int r,int L,int R) //Min
{
    if(L <= l && r <= R)return minx[x];
    pushdown(x,l,r);
    int mid = (l + r) >> 1;
    LL ans = 21474832333333LL;
    if(L <= mid)ans = min(ans,query1(ls,l,mid,L,R));
    if(R > mid)ans = min(ans,query1(rs,mid + 1,r,L,R));
    return ans;
}
inline LL query2(int x,int l,int r,int L,int R) //Sum
{
    if(L <= l && r <= R)return sum[x];
    pushdown(x,l,r);int mid = (l + r) >> 1;LL ans = 0;
    if(L <= mid)ans += query2(ls,l,mid,L,R);
    if(R > mid)ans += query2(rs,mid + 1,r,L,R);
    return ans;
}

int main()
{
    n = read(),m = read();
    for(int i=1;i<=n;i++)a[i] = Lread();
    build(1,1,n);
    while(m--)
    {
        int opt = read(),l = read() + 1,r = read() + 1;
        if(opt == 1)
        {
            int c = read();
            update1(1,1,n,l,r,c);
        }
        if(opt == 2)
        {
            int d = read();
            update2(1,1,n,l,r,d);
        }
        if(opt == 3)
        {
            LL ans = query1(1,1,n,l,r);
            printf("%lld\n",ans);
        }
        if(opt == 4)
        {
            LL ans = query2(1,1,n,l,r);
            printf("%lld\n",ans);
        }
    }
    return 0;
T1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);x = 10 * x + ch - '0',ch = getchar());
    return x * f; 
}
int n,ac,ans;
int cr[1010],cc[1010];
char ch[1010];
int main()
{
    n = read();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ch + 1);
        for(int j=1;j<=n;j++)
        {
            if(ch[j] == '#')ac++;
            if(ch[j] == '.')cr[i] ++,cc[j]++;
        }
    }
    if(!ac){puts("-1");return 0;}
    for(int i=1;i<=n;i++)if(cc[i])++ans;
    int _Ma = 2 * n + 1;
    for(int i=1;i<=n;i++)_Ma = min(_Ma,cr[i] + (cc[i] == n));
    cout<<ans + _Ma<<endl;
}
T2
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int LIM = 555;
inline int read()
{
    int x=0,f=1;char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
    for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
    return x*f;
}
const int maxn = 210010;
int n,m,k,q;
char s[maxn];
struct SAM
{
    int tr[maxn][26],fa[maxn],len[maxn],size[maxn];
    int ST[maxn][21],id[maxn],Cnt[maxn];
    int last,p,np,q,nq,cnt,rt;
    SAM(){last = ++cnt; rt = 1;}
    inline void extend(int c)
    {
        p = last, np = last = ++cnt, len[np] = len[p] + 1;size[np] = 1;
        while(!tr[p][c] && p) tr[p][c] = np, p = fa[p];
        if(!p) fa[np] = rt;
        else
        {
            q = tr[p][c];
            if(len[q] == len[p] + 1) fa[np] = q;
            else
            {
                nq = ++cnt; len[nq] = len[p] + 1; memcpy(tr[nq],tr[q],sizeof(tr[q]));
                fa[nq] = fa[q]; fa[q] = fa[np] = nq;
                while(tr[p][c] == q) tr[p][c] = nq,p = fa[p];
            }
        }
    }
    inline void buildsize()
    { 
        for(int i=1;i<=cnt;i++)Cnt[len[i]]++;
        for(int i=1;i<=n;i++)Cnt[i] += Cnt[i-1];
        for(int i=1;i<=cnt;i++)id[Cnt[len[i]]--] = i;
        for(int i=cnt;i>=1;i--)size[fa[id[i]]] += size[id[i]];
    }
    inline void STLCA()
    {
        for(int i=1;i<=cnt;i++)ST[i][0]=fa[i];
        for(int i=1;i<21;i++)for(int j=1;j<=cnt;j++)ST[j][i]=ST[ST[j][i-1]][i-1];
    }
    inline int query(int x,int va)
    {
        if(len[x] < va)return 0;
        for(int i=20;i>=0;i--)
            if(len[ST[x][i]] >= va)x = ST[x][i];
        return size[x];
    }
    inline int trans(int &now,int v,int x)
    {
        if(tr[now][x])
        {
            now=tr[now][x];
            return v + 1;
        }
        while(now && !tr[now][x])now=fa[now];
        v = len[now];
        if(tr[now][x])v++;
        now = tr[now][x];
        if(now == 0)now = 1;    
        return v;
    }
}sam;
//快来跟我写后缀自动机 写一下 调一年
struct Xianzhi{int l,r;}req[maxn];
namespace Modui_ksmall
{
    struct Query
    {
        int l,r,id;
        bool operator < (const Query &a)const
        {
            if((l / LIM) == (a.l / LIM))return r < a.r;
            return (l / LIM) < (a.l / LIM);
        }
    }qs[maxn];
    LL res[maxn],ans[LIM][LIM];
    char w[maxn][LIM];
    void solve()
    {
        for(int i=1;i<=q;i++)
        {
            scanf("%s",w[i] + 1);
            qs[i].l = read() + 1;qs[i].r = read() + 1;qs[i].id = i;
        }
        sort(qs + 1,qs + q + 1);
        int l = 0,r = 0;
        for(int i=1;i<=q;i++)
        {
            for(;l < qs[i].l;l++)ans[req[l].l][req[l].r]--;
            for(;l > qs[i].l;l--)ans[req[l - 1].l][req[l - 1].r]++;
            for(;r < qs[i].r;r++)ans[req[r + 1].l][req[r + 1].r]++;
            for(;r > qs[i].r;r--)ans[req[r].l][req[r].r]--;
            for(int s=1;s<=k;s++)
            {
                int now = 1;
                for(int t=s;t<=k;t++)
                {
                    now=sam.tr[now][w[qs[i].id][t] - 'a'];
                    if(now)res[qs[i].id] += (LL) sam.size[now] * ans[s][t]; 
                }
            }
        }
        
        for(int i=1;i<=q;i++)printf("%lld\n",res[i]);
    }
}
namespace Beizeng_klarge
{
    vector<LL> vec[maxn];
    char w[maxn];
    int v;
    void solve()
    {
        LL ans;int a,b;
        while(q--)
        {
            ans = 0;
            scanf("%s%d%d",w + 1,&a,&b);a++,b++; 
            for(int i=a;i<=b;i++)vec[req[i].r].push_back(req[i].r - req[i].l + 1);
            int now = 1,maxlen = 0;
            for(int i=1;i<=k;i++)
            {
                maxlen = sam.trans(now,maxlen,w[i] - 'a');
                for(auto j : vec[i])
                    if(maxlen >= j)ans += sam.query(now,j);
                vec[i].clear(); 
            }
            printf("%lld\n",ans);
        } 
    }
}

int main()
{
    n = read(),m = read(),q = read(),k = read();
    scanf("%s",s + 1);for(int i=1;i<=n;i++)sam.extend(s[i] - 'a');
    sam.buildsize(),sam.STLCA();
    for(int i=1;i<=m;i++)req[i].l = read() + 1,req[i].r = read() + 1;
    if(k < LIM)Modui_ksmall::solve();
    else Beizeng_klarge::solve();
}
T3_C++11

 

posted @ 2018-06-05 19:26  探险家Mr.H  阅读(240)  评论(0编辑  收藏  举报