zoukankan      html  css  js  c++  java
  • 【2019南京赛】

    hello 2019;题意:

    给出区间,要你在查询区间内有9102,同时没有8012的序列,需要删除多少个数字。

    多次询问,所以给上我们的线段树。

    这道题有原题;

    我们dp表示i从状态i到状态j的操作次数,

    我们定义0,1,2,3,4为"",2,20,201,2017的状态。对于每个状态用矩阵表示:

    如dp【1】【2】从状态为2到20;

    例如我们看其中一个地方{

    if(s[l]=='2') p[cur].a[0][0]=1,p[cur].a[0][1]=0;

    表示此刻遇到了2,那么就0状态的“”到“”,要花费1

    为什么呢,也就是我们“”遇到2,应变为2,但是你想保持“",那么就得删掉2,其他同理,

    然后就来到但是到6的时候,保持201到201需要删除6,花费价值为1。因为不能出现2016,所以从2017转移也需要删除一个价值。

    }

    代码给上:

    #include<bits/stdc++.h>
    #define ll long long
    #define inf 0x3f3f3f3f
    using namespace std;

    const int maxx=2e5+100;
    struct node{
    int a[5][5];
    node operator+(const node &b)const//重载加法
    {
    node c;
    for(int i=0;i<5;i++)
    {
    for(int j=0;j<5;j++)
    {
    c.a[i][j]=inf;
    for(int k=0;k<5;k++)
    c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
    }
    }
    return c;
    }
    }p[maxx<<2];
    char s[maxx];
    int n,m;

    inline void pushup(int cur)
    {
    p[cur]=p[cur<<1]+p[cur<<1|1];
    }
    inline void build(int l,int r,int cur)
    {
    if(l==r)
    {
    for(int i=0;i<5;i++)for(int j=0;j<5;j++) p[cur].a[i][j]=(i==j)?0:inf;
    if(s[l]=='2') p[cur].a[0][0]=1,p[cur].a[0][1]=0;
    else if(s[l]=='0') p[cur].a[1][1]=1,p[cur].a[1][2]=0;
    else if(s[l]=='1') p[cur].a[2][2]=1,p[cur].a[2][3]=0;
    else if(s[l]=='7') p[cur].a[3][3]=1,p[cur].a[3][4]=0;
    else if(s[l]=='6') p[cur].a[3][3]=1,p[cur].a[4][4]=1;
    return ;
    }
    int mid=l+r>>1;
    build(l,mid,cur<<1);
    build(mid+1,r,cur<<1|1);
    pushup(cur);
    }
    inline node query(int L,int R,int l,int r,int cur)
    {
    if(l<=L&&R<=r) return p[cur];
    int mid=L+R>>1;
    if(r<=mid) return query(L,mid,l,r,cur<<1);
    else if(l>mid) return query(mid+1,R,l,r,cur<<1|1);
    else return query(L,mid,l,mid,cur<<1)+query(mid+1,R,mid+1,r,cur<<1|1);
    }
    int main()
    {
    int l,r;
    while(~scanf("%d%d",&n,&m))
    {
    scanf("%s",s+1);
    build(1,n,1);
    while(m--)
    {
    scanf("%d%d",&l,&r);
    node ans=query(1,n,l,r,1);
    if(ans.a[0][4]==inf) printf("-1\n");
    else printf("%d\n",ans.a[0][4]);
    }
    }
    return 0;
    }

    然后2019这道题就洒洒水地将序列反转变成找2019,不要2018,所以他给出区间后,你也得反转一下再询问,

    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    #define inf 0x3f3f3f3f
    using namespace std;

    const int maxx=2e5+100;
    struct node{
    int a[5][5];
    node operator+(const node &b)const
    {
    node c;
    for(int i=0;i<5;i++)
    {
    for(int j=0;j<5;j++)
    {
    c.a[i][j]=inf;
    for(int k=0;k<5;k++)
    c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]);
    }
    }
    return c;
    }
    }p[maxx<<2];
    char s[maxx],ss[maxx];
    int n,m;

    inline void pushup(int cur)
    {
    p[cur]=p[cur<<1]+p[cur<<1|1];
    }
    inline void build(int l,int r,int cur)
    {
    if(l==r)
    {
    for(int i=0;i<5;i++)for(int j=0;j<5;j++) p[cur].a[i][j]=(i==j)?0:inf;
    if(s[l]=='2') p[cur].a[0][0]=1,p[cur].a[0][1]=0;
    else if(s[l]=='0') p[cur].a[1][1]=1,p[cur].a[1][2]=0;
    else if(s[l]=='1') p[cur].a[2][2]=1,p[cur].a[2][3]=0;
    else if(s[l]=='9') p[cur].a[3][3]=1,p[cur].a[3][4]=0;
    else if(s[l]=='8') p[cur].a[3][3]=1,p[cur].a[4][4]=1;
    return ;
    }
    int mid=l+r>>1;
    build(l,mid,cur<<1);
    build(mid+1,r,cur<<1|1);
    pushup(cur);
    }
    inline node query(int L,int R,int l,int r,int cur)
    {
    if(l<=L&&R<=r) return p[cur];
    int mid=L+R>>1;
    if(r<=mid) return query(L,mid,l,r,cur<<1);
    else if(l>mid) return query(mid+1,R,l,r,cur<<1|1);
    else return query(L,mid,l,mid,cur<<1)+query(mid+1,R,mid+1,r,cur<<1|1);
    }
    int main()
    {
    int l,r;
    while(~scanf("%d%d",&n,&m))
    {
    scanf("%s",ss+1);
    for(int i=1;i<=n;i++) s[i]=ss[n-i+1];
    build(1,n,1);
    while(m--)
    {
    scanf("%d%d",&l,&r);
    node ans=query(1,n,n-r+1,n-l+1,1);
    if(ans.a[0][4]==inf) printf("-1\n");
    else printf("%d\n",ans.a[0][4]);
    }
    }
    return 0;
    }
    //感谢大佬地博客:https://blog.csdn.net/starlet_kiss/article/details/100694910

  • 相关阅读:
    leetcode每日一题:836. 矩形重叠
    单链表之删除头结点,查找等于定值x的结点数,单链表的逆置
    拼数,零幺串
    最大公约数/最小公倍数
    寻找二叉树双亲结点
    Object类的派生-c++
    牛客小白月赛22
    二叉树的基本操作
    字符串的反转,替换,删除
    [2011山东ACM省赛] Identifiers(模拟)
  • 原文地址:https://www.cnblogs.com/hgangang/p/11516056.html
Copyright © 2011-2022 走看看