2018.3.9日记

今天又滚粗了啦qaq
早上很早起来次了点饭就去某地方考试啦ww。。
(次的很少肚子很饿qwq)
8:40开始考试
一开始就想睡觉啊qwq 可我连一道题都还没看呐
T1题意很简单,n条线段,Q组询问,每组询问给出m个点,问有多少条线段覆盖了奇数个点。
看起来。。除了暴力没有任何思路诶,于是打完暴力跳过。

T2字符串题,又是果断放弃qwq 暴力浪费了我一个小时,只是拿了10分嘤

T3好像有点思路,先把暴力分20分秒了,然后想想想,矩阵快速幂?又想了一下好像NTT?模数1e9+7不够常见,就算我会NTT那个G我也找不出来啊,好像和暴力的跨度有点大?算了还是先想T1吧,好像它最可做。

pa了一会儿突然想到了方法,对于m<=50,Q<=100000,n<=100000的点显然可做,线段覆盖的一定是连续的点,那么枚举覆盖了哪些点,O(m^2),然后可以知道对应线段的左端点和右端点可在的范围,然后就很经典啦,主席树?!

想到这个之后我还不如没想到,因为我主席树几乎没有打过,就很久以前打了一棵可持久化权值线段树,忘了qwq。。时间还剩半小时,算了放弃吧,满分将上述方法和暴力结合即可。。听说很多人都被卡常了?但是这个时间复杂度确实合理地啊。。
贴上我可怜的代码吧(好遗憾啊

//Suplex
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 100000+100
using namespace std;
int t[5000000],L[5000000],R[5000000],tot,n,m,now,root[N],b[N],A,B,C,D,Q,ans,s[N];

struct segment{
    int l,r;
}a[N];

inline bool cmp(segment a,segment b){
    return a.l<b.l || a.l==b.l && a.r<b.r;
}

inline void insert(int &p,int rt,int l,int r,int x){
    p=++tot;
    t[p]=t[rt]+1;
    if(l==r) return;
    L[p]=L[rt];R[p]=R[rt];
    int mid=(l+r)>>1;
    if(x<=mid) insert(L[p],L[rt],l,mid,x);
    else insert(R[p],R[rt],mid+1,r,x);
}

inline int query(int le,int ri,int l,int r,int x,int y){
    if(x>y) return 0;
    if(x>r || y<l) return 0;
    if(x<=l && r<=y) return t[ri]-t[le];
    int mid=(l+r)>>1;
    return query(L[le],L[ri],l,mid,x,y)+query(R[le],R[ri],mid+1,r,x,y);
}

int main()
{
    freopen("segment.in","r",stdin);
    freopen("segment.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].l,&a[i].r);
    sort(a+1,a+1+n,cmp);
    now=1;
    for(int i=1;i<=n;i++){
        root[i]=root[i-1];
        while(now<=n && a[now].l==i) insert(root[i],root[i],1,n,a[now].r),now++;
    }
    scanf("%d",&Q);
    while(Q--){
        scanf("%d",&m);
        for(int i=1;i<=m;i++) scanf("%d",&b[i]);
        sort(b+1,b+1+m);
        if(m<=50){
            ans=0;
            b[0]=0;b[m+1]=n+1;
            for(int i=1;i<=m;i++){
                if(i % 2==0) continue;
                for(int j=1;j<=m-i+1;j++){
                    A=b[j-1];B=b[j];
                    C=b[j+i-1];D=b[j+i]-1;
                    ans+=query(root[A],root[B],1,n,C,D);
                }
            }
            printf("%d\n",ans);
        }else{
            for(int i=1;i<=n;i++) s[i]=0;
            for(int i=1;i<=m;i++) s[b[i]]++;
            for(int i=1;i<=n;i++) s[i]+=s[i-1];
            ans=0;
            for(int i=1;i<=n;i++) if((s[a[i].r]-s[a[i].l-1]) % 2) ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值