#6201. 「YNOI2016」掉进兔子洞
您正在打galgame,然后突然发现您今天太颓了,于是想写个数据结构题练练手:
给出一个长为 nnn 的序列 aaa。
有 mmm 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的个数和,询问独立。
注意这里删掉指的是一个一个删,不是把等于这个值的数直接删完,比如三个区间是 [1,2,2,3,3,3,3][1,2,2,3,3,3,3][1,2,2,3,3,3,3] , [1,2,2,3,3,3,3][1,2,2,3,3,3,3][1,2,2,3,3,3,3] 与 [1,1,2,3,3][1,1,2,3,3][1,1,2,3,3],就一起扔掉了 111 个 111,111 个 222,222 个 333。
输入格式
第一行两个数表示 nnn , mmm。
第二行 nnn个数表示 aia_iai。
之后 mmm 行,每行 666 个数 l1l_1l1 , r1r_1r1 , l2l_2l2 , r2r_2r2 , l3l_3l3 , r3r_3r3 表示这三个区间。
输出格式
对于每个询问,输出一个数表示答案。
样例
SAMPLE INPUT
5 2
1 2 2 3 3
1 2 2 3 3 4
1 5 1 5 1 5
SAMPLE OUTPUT
3
0
数据范围与提示
1≤n,m≤1051 \leq n,m \leq 10^{5}1≤n,m≤105 , 1≤ai≤1091 \leq a_i \leq 10^{9}1≤ai≤109
#include#include #include #include #include #include #define maxn 100010 using namespace std; int n,a[maxn],b[maxn],cnt[maxn],pos[maxn],block,tot,ans[maxn],T=25000; bool mark[maxn]; struct node{int l,r,id;}q[maxn]; bitset<100000>F[25001],f; bool cmp(node a,node b){ if(pos[a.l]==pos[b.l])return a.r<b.r; return pos[a.l]<pos[b.l]; } void update(int k,int ty){ k=a[k];cnt[k]+=ty; if(ty==1)f[k+cnt[k]-2]=1; else f[k+cnt[k]-1]=0; } void solve(int m){ int L,R,l1,l2,l3,r1,r2,r3; memset(cnt,0,sizeof(cnt)); memset(mark,0,sizeof(mark)); f.reset();tot=0; for(int i=1;i<=m;i++){ scanf("%d%d%d%d%d%d",&l1,&r1,&l2,&r2,&l3,&r3); q[++tot]=(node){l1,r1,i}; q[++tot]=(node){l2,r2,i}; q[++tot]=(node){l3,r3,i}; ans[i]=r3+r2+r1-l3-l2-l1+3; } sort(q+1,q+tot+1,cmp); L=1;R=0; for(int i=1;i<=tot;i++){ while(R 1); while(R>q[i].r)update(R--,-1); while(L1); while(L>q[i].l)update(--L,1); if(mark[q[i].id])F[q[i].id]&=f; else F[q[i].id]=f,mark[q[i].id]=1; } for(int i=1;i<=m;i++){ int k=F[i].count(); printf("%d\n",ans[i]-3*k); } } int main(){ int m; scanf("%d%d",&n,&m); block=sqrt(n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; pos[i]=(i-1)/block+1; } sort(b+1,b+n+1); for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+n+1,a[i])-b; while(m){ if(m<=T)solve(m),m=0; else solve(T),m-=T; } return 0; }