zoukankan      html  css  js  c++  java
  • 19_03_28校内训练[相似字符串]

    题意

    给出一个长度为n的序列,有m次询问,每次询问[l1,r1],[l2,r2]的区间,问排序后相同位置的不同数字个数是否小于等于1。如[1,3,2,2],[1,3,2,3]排序后为[1,2,2,3]和[1,2,3,3],不同的有2个,不符合。n,m≤1,000,000,数的大小≤50,000。


    思考

    有排序,权值还小,自然想到可持久化线段树。

    不同数小于等于1,自然先想完全相同的条件。

    先以权值为下表,按加入数组的顺序加入可持久化线段树,这样得到了1~n不同大小的数的前缀和。

    若是完全相同,先做一次r-(l-1),由于排序后的数,相同的没有位置关系,哈希即可。

    有一个不同?则必然存在最左边和最右边的端点,使得该位置上出现的数的个数不同。不同的数超过2个,及不符合(实际上是1,但会算两边)。否则再查询这个开区间中,是否还有其余数。若有,显然不满足。否则满足。

    线段树上二分即可。O(nlogn+mlogn)。

    记得不要用hash这个变量名就能过了。


    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long int ll;
      4 const ll h1=13131;
      5 const ll h2=23333;
      6 const ll h3=15787;
      7 const ll mod1=1000000007;
      8 const ll mod2=998244353;
      9 const ll mod3=19260817;
     10 const ll maxn=1E5+5;
     11 ll q1[maxn],q2[maxn],q3[maxn],maxx=100000;
     12 int read()
     13 {
     14     char ch=getchar();
     15     while(ch<'0'||'9'<ch)ch=getchar();
     16     int sum=ch-'0';
     17     ch=getchar();
     18     while('0'<=ch&&ch<='9')
     19     {
     20         sum=sum*10+ch-'0';
     21         ch=getchar();
     22     }
     23     return sum;
     24 }
     25 struct Hash
     26 {
     27     ll a1,a2,a3;
     28     int sum;
     29     Hash(ll x=0,ll y=0,ll z=0,ll s=0){a1=(x+mod1)%mod1,a2=(y+mod2)%mod2,a3=(z+mod3)%mod3,sum=s;}
     30     void operator=(Hash x){a1=x.a1,a2=x.a2,a3=x.a3,sum=x.sum;}
     31     Hash operator+(Hash x){return Hash(a1+x.a1,a2+x.a2,a3+x.a3,sum+x.sum);}
     32     Hash operator-(Hash x){return Hash(a1-x.a1,a2-x.a2,a3-x.a3,sum-x.sum);}
     33     bool operator==(Hash x){return a1==x.a1&&a2==x.a2&&a3==x.a3;}
     34 }t[maxn*20],g[maxn];
     35 int ls[maxn*20],rs[maxn*20],T,n,m,cur,a[maxn],root[maxn];
     36 void init()
     37 {
     38     q1[0]=q2[0]=q3[0]=1;
     39     for(int i=1;i<=100000;++i)
     40     {
     41         q1[i]=q1[i-1]*h1%mod1;
     42         q2[i]=q2[i-1]*h2%mod2;
     43         q3[i]=q3[i-1]*h3%mod3;
     44         g[i]=Hash(q1[i],q2[i],q3[i],1);
     45     }
     46 }
     47 void insert(int l,int r,int pos,int&num,int pre)
     48 {
     49     num=++cur;
     50     t[num]=t[pre];
     51     ls[num]=ls[pre];
     52     rs[num]=rs[pre];
     53     t[num]=t[num]+g[pos];
     54     if(l==r)return;
     55     int mid=(l+r)>>1;
     56     if(pos<=mid)insert(l,mid,pos,ls[num],ls[pre]);
     57     else insert(mid+1,r,pos,rs[num],rs[pre]);
     58 }
     59 int GGAx,GGAy,GGAz,GGBx,GGBy,GGBz;
     60 void findL(int l,int r,int l1,int r1,int l2,int r2)
     61 {
     62     if(l==r)
     63     {
     64         GGAx=l;
     65         GGAy=t[r1].sum-t[l1].sum;
     66         GGAz=t[r2].sum-t[l2].sum;
     67         return;
     68     }
     69     int mid=(l+r)>>1;
     70     Hash L1=t[ls[r1]]-t[ls[l1]],R1=t[rs[r1]]-t[rs[l1]];
     71     Hash L2=t[ls[r2]]-t[ls[l2]],R2=t[rs[r2]]-t[rs[l2]];
     72     if(!(L1==L2))
     73     {
     74         l1=ls[l1],r1=ls[r1];
     75         l2=ls[l2];r2=ls[r2];
     76         findL(l,mid,l1,r1,l2,r2);
     77     }
     78     else
     79     {
     80         l1=rs[l1],r1=rs[r1];
     81         l2=rs[l2],r2=rs[r2];
     82         findL(mid+1,r,l1,r1,l2,r2);
     83     }
     84 }
     85 void findR(int l,int r,int l1,int r1,int l2,int r2)
     86 {
     87     if(l==r)
     88     {
     89         GGBx=l;
     90         GGBy=t[r1].sum-t[l1].sum;
     91         GGBz=t[r2].sum-t[l2].sum;
     92         return;
     93     }
     94     int mid=(l+r)>>1;
     95     Hash L1=t[ls[r1]]-t[ls[l1]],R1=t[rs[r1]]-t[rs[l1]];
     96     Hash L2=t[ls[r2]]-t[ls[l2]],R2=t[rs[r2]]-t[rs[l2]];
     97     if(!(R1==R2))
     98     {
     99         l1=rs[l1],r1=rs[r1];
    100         l2=rs[l2],r2=rs[r2];
    101         findR(mid+1,r,l1,r1,l2,r2);
    102     }
    103     else
    104     {
    105         l1=ls[l1],r1=ls[r1];
    106         l2=ls[l2];r2=ls[r2];
    107         findR(l,mid,l1,r1,l2,r2);
    108     }
    109 }
    110 int askSeq(int L,int R,int l,int r,int num)
    111 {
    112     if(L>R)return 0;
    113     if(L<=l&&r<=R)return t[num].sum;
    114     else if(r<L||R<l)return 0;
    115     int mid=(l+r)>>1;
    116     return askSeq(L,R,l,mid,ls[num])+askSeq(L,R,mid+1,r,rs[num]);
    117 }
    118 void YES(){putchar('Y');putchar('E');putchar('S');putchar('\n');}
    119 void NO(){putchar('N');putchar('O');putchar('\n');}
    120 void solve()
    121 {
    122     n=read();m=read();
    123     for(int i=1;i<=n;++i)
    124     {
    125         a[i]=read();
    126         insert(1,maxx,a[i],root[i],root[i-1]);
    127     }
    128     while(m--)
    129     {
    130         int l1,r1,l2,r2;
    131         l1=read();r1=read();l2=read();r2=read();
    132         if(l1>r1)swap(l1,r1);
    133         if(l2>r2)swap(l2,r2);
    134         if(t[root[r1]]-t[root[l1-1]]==t[root[r2]]-t[root[l2-1]])YES();
    135         else
    136         {
    137             findL(1,maxx,root[l1-1],root[r1],root[l2-1],root[r2]);
    138             findR(1,maxx,root[l1-1],root[r1],root[l2-1],root[r2]);
    139             int x=GGAx;
    140             int y=GGBx;
    141             int d1=askSeq(x+1,y-1,1,maxx,root[r1])-askSeq(x+1,y-1,1,maxx,root[l1-1]);
    142             int d2=askSeq(x+1,y-1,1,maxx,root[r2])-askSeq(x+1,y-1,1,maxx,root[l2-1]);
    143             if(abs(GGAy-GGAz)+abs(GGBy-GGBz)>2||d1!=0||d2!=0)NO();
    144             else YES();
    145         }
    146     }
    147 }
    148 void clear()
    149 {
    150     for(int i=0;i<=cur;++i)t[i].a1=t[i].a2=t[i].a3=ls[i]=rs[i]=0;
    151     for(int i=0;i<=n;++i)root[i]=0;
    152     cur=0;
    153 }
    154 int main()
    155 {
    156 //    freopen("sequence.in","r",stdin);
    157 //    freopen("sequence.out","w",stdout);
    158     ios::sync_with_stdio(false);
    159     init();
    160     T=read();
    161     while(T--)
    162     {
    163         solve();
    164         if(T!=0)clear();
    165     }
    166     return 0;
    167 }
    View Code
  • 相关阅读:
    30 分钟快速入门 Docker 教程
    python functools.wraps
    计算机科学中最重要的32个算法
    JDBC的作用及重要接口
    SSO单点登录--支持C-S和B-S
    谈谈Sql server 的1433端口
    屏蔽:粘贴到KindEditor里,IE下弹出框报”对象不支持moveToElementText属性或方法“错误的提示
    markdown
    ddd
    python进阶学习(一)--多线程编程
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/10616904.html
Copyright © 2011-2022 走看看