2020牛客多校第二场G

题意:给你两个序列,问你从第一个序列中有多少个与第二个序列长度相同的并且对应位置都是大于等于第二个序列的子串。

题解: 神仙bitset题,维护第二个序列的bitset,例如样例中的 2 3 3,按照大小排序后维护的m个bitset为:0100,0110,0111,,样例中的数据维护的bitset不是很好理解,在举一个例子比如:2 4 5 3 6,按照大小排序后的m个bitset为:010000,010010,011010,011110,011111,维护出第二个序列的bitset后我们就可以通过bitset的&操作求得答案了,我们在维护好m个bitset后对于第一个序列,我门可以通过二分的去找到第二个序列中小于等于它的最大的位置,得到它可以放的位置的bitset信息,我们考虑从左往右或者从右往左在维护一个bitset,初始化全为0,当我们从后往前时,如果当前的数大于等于第二个序列的第m个数,那么将我们维护的bitset第m为赋值为1,往左走将维护的bitset对应左移一位后与当前位置的bitset信息取&后为1,那么就代表从右边的某个数作为最后一个数,到当前位置是可以作为第二个序列的最后几位数的,是满足条件的,然后继续执行下去,如果第1位为1了那么说明肯定存在一个长度为m的子串是满足条件的,答案加一。

AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#include 
#define ls (k<<1)
#define rs ((k<<1)|1)
#define mid ((l+r)>>1)
using namespace std;
using namespace std;
const int maxn=150010;
const int maxm=40010;
const int inf=1e9+7;
bitset cur,s[maxm];
int ai[maxn],bi[maxm],ci[maxm];
struct node{
    int id,va;
}qi[maxm];
bool cmp(node a,node b){
    if(a.va==b.va) return a.id=1;a--){
        cur>>=1;
        int k;
        if(ai[a]>=ci[m]) k=m;
        else k=upper_bound(ci+1,ci+m+1,ai[a])-ci-1;
        cur&=s[k];
        if(ai[a]>=bi[m]) cur.set(m-1);
        ans+=cur[0];
    }
    printf("%d\n",ans);
}
/*
6 3
1 4 2 8 5 7
2 8 3
 */

 

你可能感兴趣的:(ACM,数据结构,算法)