2013多校3部分题题解报告

来源:互联网 发布:考试系统的数据流程图 编辑:程序博客网 时间:2024/05/23 02:01

·先谢WJMZBMR.....这套题虽然难度较大,但很有价值(世界冠军出的题怎能没价值。。。)

1007

送分题,略

1010

拿到题之后完全不知道怎么做,后来看了kuangbin的博客才知道怎么处理。。。(kuangbin大牛写的挺好的,赞一个~)

把a[l]~a[r]约数都找到,其实就是查询该区间内出现2次以上的最大数

最直接的区间合并是根本不行的,而这个时候就要换一种思路,那就是离线处理,并且更新线段树要随着数据读入同时更新,而不是先读好数,然后再更新。

首先是离线处理,按照起始点排序,因为插入元素时,是从右往左做的。

具体情况是这样,假设扫面指针指向i,用tre[j]存储的数是约数x上一次出现的位置,如果同个位置出现多个约数,只记录做大的,用线段树维护,用a[i]维护约数i所在的最新位置

附代码:

#include <iostream>#include <cstdio>#include <vector>#define N 50005#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define cl(a) memset(a,0,sizeof(a))#define ss(a) scanf("%d",&a)#define pb push_backstruct interval{    int lpot;    int rpot;    int id;};using namespace std;int b[N],tre[N<<2],a[N],pr[N];interval q[N];vector<int>d[N];void init(){    int i,j;    for (i=1;i<N;i++)        for (j=1;j*j<=i;j++)            if (i%j==0)             {                d[i].pb(j);                if (j*j!=i) d[i].pb(i/j);            }}bool cmp(interval x,interval y){    return x.lpot>y.lpot;}void pushup(int rt){    tre[rt]=max(tre[rt<<1],tre[rt<<1|1]);}void update(int i,int x,int l,int r,int rt){    if (l==r)    {        if (x>tre[rt]) tre[rt]=x;        return;    }    int mid=(l+r)>>1;    if (i<=mid) update(i,x,lson);    else update(i,x,rson);    pushup(rt);}int query(int L,int R,int l,int r,int rt){    if (L<=l&&r<=R) return tre[rt];    int mid=(l+r)>>1,res=0;    if (L<=mid) res=max(res,query(L,R,lson));    if (R>mid) res=max(res,query(L,R,rson));    return res;}int main(){    int i,n,z,T,m,j;    ss(T);    init();    while (T--)    {        ss(n);        for (i=1;i<=n;i++) ss(a[i]);        ss(m);        for (i=1;i<=m;i++)         {            ss(q[i].lpot);ss(q[i].rpot);            q[i].id=i;        }        cl(b);cl(tre);        int z=1;        sort(q+1,q+m+1,cmp);        for (i=n;i>=1;i--)        {            int x=a[i];            for (j=0;j<d[x].size();j++)            {                int t=d[x][j];                if (!b[t]) b[t]=i;                else                 {                    update(b[t],t,1,n,1);                    b[t]=i;                }            }            while (i==q[z].lpot&&z<=m)            {                pr[q[z].id]=query(q[z].lpot,q[z].rpot,1,n,1);                z++;            }            if (z>m) break;        }        for (i=1;i<=m;i++) printf("%d\n",pr[i]);    }    return 0;}