0 1 1000000 1000000 50 1 1000000 999999 0 1 1000000 999999 0 1 1000000 1000000 49 2 1000000 1000000 1000000 2 1000000 1 1000000 0 1 1 1 1 2 1 1 2 1 1 2 2 2 1 1 2 1 2 2 2 2 1 1 2 1 2 1 3 2 2 1 2 2 10 1 2 2 10 2 2 0 1 1 1 1 2 1 1 1 1 1 2 1 2 1 1 2 1 2 2 1 2 1 1 2 1 2 1 1 2 2 1 2 2 10 1 2 2 10 2 2 3Sample Output
2 3 1 2 2 3 3 1 1 1 1 1 1 1
分析:颜色只有50个,可以考虑用一个long long来表示,:这题的查询操作很特殊,每次查询的是一个紧贴着y轴的矩阵中的颜色数,所以我们只需要用线段树维护纵轴方向的颜色集合,那么每次查询就是横轴上的一个前缀和,修改操作只要用cdq分治对时间进行分治就把修改时间这一维忽略了,剩下的就是按横标从左到右动态插入和查询答案,直接用动态开点线段树解决,总复杂度n*logn(线段树)*logn(cdq对时间的分治)。
#include
using namespace std;
const int N = 2e6;
typedef long long ll;
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
class thing
{
public:
int op,x,y,z,t,lab;
friend bool operator < (const thing &a,const thing &b)
{
if(a.x != b.x) return a.x < b.x;
return a.t < b.t;
}
}job[N],work[N],tmp[N];
int n,num,cnt,root,tot,ch[N*2][2];
ll ans[N],mask[N*2];
int Count(ll x)
{
int cnt = 0;
while(x)
{
cnt++;
x -= x & (-x);
}
return cnt;
}
void Insert(int &u,int l,int r,int x,int val)
{
if(!u) u = ++cnt;
mask[u] |= 1ll<>1;
if(x <= mid) Insert(ch[u][0],l,mid,x,val);
else Insert(ch[u][1],mid+1,r,x,val);
}
ll Query(int u,int l,int r,int x,int y)
{
if(!u) return 0;
if(l == x && r == y) return mask[u];
int mid = (l+r)>>1;
if(y <= mid) return Query(ch[u][0],l,mid,x,y);
else
if(x <= mid) return Query(ch[u][0],l,mid,x,mid) | Query(ch[u][1],mid+1,r,mid+1,y);
else return Query(ch[u][1],mid+1,r,x,y);
}
void Del(int &u)
{
if(!u) return;
Del(ch[u][0]);
Del(ch[u][1]);
mask[u] = 0;
u = 0;
}
void cdq(int l,int r)
{
if(l >= r) return;
int mid = (l+r)>>1;
for(int i = l;i <= r;i++)
if(work[i].op == 1 && work[i].t <= mid) Insert(root,1,1e6,work[i].y,work[i].z);
else
if(work[i].op == 2 && work[i].t > mid) ans[work[i].lab] |= Query(root,1,1e6,work[i].y,work[i].z);
Del(root);
cnt = 0;
int l1 = l-1,r1 = mid;
for(int i = l;i <= r;i++)
if(work[i].t <= mid) tmp[++l1] = work[i];
else tmp[++r1] = work[i];
for(int i = l;i <= r;i++) work[i] = tmp[i];
cdq(l,mid);
cdq(mid+1,r);
}
void deal(int l,int r)
{
if(l > r) return;
n = r - l + 1;
num = 0;
for(int i = l;i <= r;i++)
if(job[i].op == 2) job[i].lab = ++num;
for(int i = l;i <= r;i++)
{
work[i-l+1] = job[i];
work[i-l+1].t = i-l+1;
}
sort(work+1,work+1+n);
cdq(1,n);
for(int i = 1;i <= num;i++)
{
cout<