P8955 「VUSC」Card Tricks 解题报告
P8955 「VUSC」Card Tricks 解题报告
简要题意
给出一个长度为 \(n\) 的序列 \(\{a\}\) 和 \(m\) 次操作,每次操作都为给一段区间按位或上一个数。给定数 \(P\),求对于每一个 \(a_i\),求其第一次严格大于 \(P\) 时的操作数。
其中,\(n,q \le 10^6\) ,\(P,a_i \le 10^9\)
分析
区间按位或?第一次?整体二分!
10分钟打完,一交,喜提TLE。
\(O((n+m)\log n\log m)\) ,接近 \(7 \times 10^9\),确实不太行。
分析算法瓶颈在于每次二分时都需要把二分区间的操作再做一遍。这是很幽默的,因为所有操作都已经给出来了,为什么不预处理一下呢?
所以我们考虑对序列维度进行扫描线,用线段树维护操作,对于序列维度上的每一个点,处理完当前操作后就在线段树上跑线段树二分。
时间复杂度 \(O((n+m)\log n)\),非常优美,直接跑到最优解第一页.
代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Inf (1ll<<60)
#define For(i,s,t) for(int i=s;i<=t;++i)
#define Down(i,s,t) for(int i=s;i>=t;--i)
#define ls (i<<1)
#define rs (i<<1|1)
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x>y?x:y;}
inline ll min(ll x,ll y){return x<y?x:y;}
inline ll max(ll x,ll y){return x>y?x:y;}
inline int read(){
register int x=0,f=1;
char c=getchar();
while(c<'0' || '9'<c) f=(c=='-')?-1:1,c=getchar();
while('0'<=c && c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
return x*f;
}
void write(int x){
if(x>=10) write(x/10);
putchar(x%10+'0');
}
const int N=1e6+100;
int n,q,p,val[N];
struct Tree{int l,r,val;}t[N<<2];
void push_up(int i){t[i].val=(t[ls].val|t[rs].val);}
void build(int i,int l,int r){
t[i].l=l,t[i].r=r;
if(l==r) return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void update(int i,int x,int k){
if(t[i].l==t[i].r){
t[i].val=k;
return;
}
int mid=t[i].l+t[i].r>>1;
if(x<=mid)
update(ls,x,k);
else
update(rs,x,k);
push_up(i);
}
int result;
void query(int i,int x){
if(t[i].l==t[i].r) {result=t[i].l;return;}
int mid=t[i].l+t[i].r>>1;
(x|t[ls].val)<=p?query(rs,x|t[ls].val):query(ls,x);
}
struct Node{int tim,pos,val;}a[N<<1];
bool cmp(Node x,Node y){return x.tim<y.tim;}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
n=read(),q=read(),p=read();
For(i,1,n) val[i]=read();
For(i,1,q) a[i*2-1].tim=read(),a[i*2].tim=read()+1,a[i*2-1].val=read(),a[i*2].pos=a[i*2-1].pos=i;
sort(a+1,a+2*q+1,cmp);
int ind=1;
build(1,1,q);
For(i,1,n){
while(ind<=(q<<1) && a[ind].tim<=i) update(1,a[ind].pos,a[ind].val),++ind;
if((val[i]|t[1].val)<= p){putchar('-'),putchar('1'),putchar(' ');continue;}
query(1,val[i]),write(result),putchar(' ');
}
return 0;
}

浙公网安备 33010602011771号