天天爱射击
题目链接:天天爱射击考虑每个木板。一定是穿过的第 s[i]s[i]s[i] 个子弹为其贡献一次答案。所以我们可以对所有木板整体二分子弹的时间线。但是有一个 logloglog 的做法,我们可以离线木板,用主席树区间查询第几个子弹的时间。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h&
·
题目链接:天天爱射击
考虑每个木板。一定是穿过的第 s [ i ] s[i] s[i] 个子弹为其贡献一次答案。
所以我们可以对所有木板整体二分子弹的时间线。但是有一个 l o g log log 的做法,我们可以离线木板,用主席树区间查询第几个子弹的时间。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10,M=N*40;
int n,m,rt[N],lc[M],rc[M],sum[M],cnt,mx,res[N];
struct node{int l,r,s;}t[N];
vector<int> v[N];
#define mid (l+r>>1)
void change(int l,int r,int x,int &y,int k){
y=++cnt,lc[y]=lc[x],rc[y]=rc[x],sum[y]=sum[x]+1;
if(l==r) return ;
if(k<=mid) change(l,mid,lc[x],lc[y],k);
else change(mid+1,r,rc[x],rc[y],k);
}
int ask(int l,int r,int x,int y,int k){
if(l==r) return l;
if(sum[lc[y]]-sum[lc[x]]>=k) return ask(l,mid,lc[x],lc[y],k);
else return ask(mid+1,r,rc[x],rc[y],k-(sum[lc[y]]-sum[lc[x]]));
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d %d %d",&t[i].l,&t[i].r,&t[i].s),mx=max(mx,t[i].r);
for(int i=1,x;i<=m;i++) scanf("%d",&x),mx=max(mx,x),v[x].push_back(i);
for(int i=1;i<=mx;i++){
rt[i]=rt[i-1];
for(int j=0;j<v[i].size();j++) change(1,m,rt[i],rt[i],v[i][j]);
}
sort(t+1,t+1+n,[](node a,node b){return a.r<b.r;});
for(int i=1;i<=n;i++) if(sum[rt[t[i].r]]-sum[rt[t[i].l-1]]>=t[i].s)
res[ask(1,m,rt[t[i].l-1],rt[t[i].r],t[i].s)]++;
for(int i=1;i<=m;i++) printf("%d\n",res[i]);
return 0;
}
更多推荐
已为社区贡献1条内容
所有评论(0)