CDOJ 1104 求两个数列的子列的交集 查询区间小于A的数有多少个 主席树
求两个数列的子列的交集
Time Limit: 1 Sec
Memory Limit: 256 MB
题目连接
http://acm.uestc.edu.cn/#/problem/show/1104Description
给两个数列A, B,长度分别为n1, n2,保证A中每个元素互不相同,保证B中每个元素互不相同
。。进行Q次询问,每次查找A[l1...r1]和B[l2..r2]的交集 集合 大小是多少。。
比如 A = {1,2,3,4,5,6,7},B = {7,6,5,4,3,2,1}
查询A[2..4]和B[3..5]。。A[2..4] = {2,3,4};B[3..5] = {5,4,3},交集为{3,4},大小为2。。
Input
第一行输入n1,第二行输入n1个数;同样,第三行输入n2,第四行输入n2个数。
第五行输入Q。。接下来Q行输入l1, r1, l2, r2。。
保证 n1, n2, Q在[1, 2×105]范围内,1≤l1≤r1≤n1,1≤l2≤r2≤n2,然后数在[−109,109]范围内。。
Output
输出Q行,表示答案。。
Sample Input
7
1 2 3 4 5 6 7
7
7 6 5 4 3 2 1
1
2 4 3 5
Sample Output
2
HINT
题意
题解:
主席树裸题,查询区间小于a的数有多少个就好了
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <bitset> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 200500 #define mod 1001 #define eps 1e-9 #define pi 3.1415926 int Num; //const int inf=0x7fffffff; const ll inf=999999999; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } //************************************************************************************* int a[maxn],b[maxn],lb,n,m; struct segmenttree { int l,r,s; }tree[maxn*25]; int node; int root[maxn]; int search(int x) { int l=0,r=lb,mid; while (l<r) { mid=l+r+1>>1; if(b[mid]<=x) l=mid; else r=mid-1; } return l; } int build(int l,int r) { int k=++node; tree[k].s=0; if(l==r) return k; int m=l+r>>1; if(l<=m) tree[k].l=build(l,m); if(r>m) tree[k].r=build(m+1,r); return k; } int change(int rt,int l,int r,int x) { int k=++node,root=k,mid; tree[k]=tree[rt]; tree[k].s++; while (l<r) { mid=l+r>>1; if(x<=mid) { rt=tree[rt].l; tree[k].l=++node; k=node; tree[k]=tree[rt]; tree[k].s++; r=mid; } else { rt=tree[rt].r; tree[k].r=++node; k=node; tree[k]=tree[rt]; tree[k].s++; l=mid+1; } } return root; } int query(int L,int R,int l,int r,int x) { int mid,ans=0; while (l<r) { mid=l+r>>1; if(mid>=x) { r=mid; L=tree[L].l; R=tree[R].l; } else { l=mid+1; ans+=tree[tree[R].l].s-tree[tree[L].l].s; L=tree[L].r; R=tree[R].r; } } if(l==r) { if(x<l) return 0; else return ans+tree[R].s-tree[L].s; } } int get(int l,int r,int val) { val = search(val); if(val==0)return 0; return query(root[l-1],root[r],1,lb,val); } int A[maxn]; int main() { int nn=read(); for(int i=1;i<=nn;i++) A[i]=read(); sort(A+1,A+nn+1); int n=read(); for(int i=1;i<=n;i++) { int x=read(); int l = 1,r = nn; while(l<=r) { int mid = (l+r)>>1; if(A[mid]==x) {a[i]=x;break;} if(A[mid]<x)l=mid+1; else r = mid-1; } if(a[i]==0)a[i]=inf; } lb=1; for(int i=1;i<=n;i++) b[i]=a[i]; lb=1; sort(b+1,b+1+n); for(int i=2;i<=n;i++) if(b[i]!=b[lb])b[++lb]=b[i]; node = 0; root[0]=build(1,lb); for(int i=1;i<=n;i++) root[i]=change(root[i-1],1,lb,search(a[i])); int m=read(); for(int i=1;i<=m;i++) { int n1=read(),n2=read(),n3=read(),n4=read(); printf("%d\n",get(n3,n4,n2)-get(n3,n4,n1-1)); } }