2017-07-12:分块(SOJ1939)+中位数(SOJ1938)

来源:互联网 发布:sql server 2008 免费 编辑:程序博客网 时间:2024/04/30 21:32

2017-07-11考试第三题:一道不断加数,删数,查数的题
1.在集合中加入数字 s ;
2.在集合中删除数字 s ,保证 s 存在,如果有多个 s,只删除一个即可;
3.查询满足 a&s=a 条件的 a 的个数;
第一眼以为是线段树,但实际上并不是。
思想是分块处理:
由于数据大小是2^16,于是分为2^8*2^8,把一个数分为前八位和后八位

    pre=x>>8;    suf=x%256;

pre用来找集合,suf用来枚举集合中的数
注意:
用pre来找集合的时候,是要把pre丢进集合中,要用pre来进行比较
用suf在集合中枚举数的时候,是寻找集合中的数,要用集合中的数进行比较
丢数时要把满足pre的所有集合里面丢进数,找数时只枚举pre集合中的数

    add:    for (int i=0;i<=255;i++)        if ((pre&i)==pre)            a[i][suf]++;    del:    for (int i=0;i<=255;i++)        if ((pre&i)==pre)            a[i][suf]--;    cnt:    for (int i=0;i<=255;i++)        if ((sur&i)==i)            ans+=a[pre][i];

2017-07-12考试第二题:求以i为中位数的最长数列长度
思想:以待求数为节点,分别向前向后枚举,用cnt计数,注意下标为第二关键字

    l[i]:在待求点左侧状态为i的最长距离    r[i]:在待求点右侧状态为i的最长距离
    for (int i=1;i<=n;i++){        cnt=0;        memset(l,0,sizeof(l));        memset(r,0,sizeof(r));        l[n]=i;        r[n]=i;        for (int j=i-1;j>=1;j--){            if (a[i]>=a[j])                cnt--;            else                cnt++;            l[n+cnt]=j;        }        cnt=0;        for (int j=i+1;j<=n;j++){            if (a[i]<=a[j])                cnt++;            else                cnt--;            r[n+cnt]=j;        }        b[i]=1;        for (int j=-n;j<=n;j++)            if (r[n-j] && l[n+j])                b[i]=max(b[i],r[n-j]-l[n+j]+1);    }
原创粉丝点击