懒得搬题面QAQ
看到这题一眼莫队hhhhhh
但是数据离散化得用hash
因为莫队还得支持插入和删除
然后还得支持重复利用cnt
所以我打了1800K+接近2hQAQ
好菜啊QAQ
主要是hash比较不熟。。
莫队真是好东西
不过其实这道题很多都可以写
树套树。。(忘记线段树套平衡树怎么写了QAQ)
还有O(N)的做法(可以看成是扫描线吧QAQ)
把询问的l和r拆开
然后sum[r]-sum[l-1]就可以了
还是支持莫队QAQ
做法1:莫队
1e5的数据时间0.7s左右
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
const int N=1e5+100,mod=1e7+19;
struct node
{
int l,r,x,order;
}e[N];
struct edgt
{
int next,val;
void clear()
{
next=0,val=0;
}
}f[N];
int m;
int first[mod+20],cnt=0;
bool ans[N];
int vi[N];
int pos[N];
int qu[N+10];
int head=1,tail=1;
int getnum()
{
int d=qu[head++];if(head==N) head=0;
return d;
}
void add(int x)
{
qu[tail++]=x;if(tail==N) tail=0;
}
void gethash(int x)
{
int end=x%mod;
int tot=getnum();
f[tot].next=first[end];first[end]=tot;f[tot].val=x;
}
void del(int x)
{
int end=x%mod;
int pre=0;
int k=first[end];
pre=k;
if(f[k].val==x)
{
first[end]=f[k].next,f[k].clear(),add(k);
return;
}
k=f[k].next;
for(;k;k=f[k].next)
{
if(f[k].val==x) f[pre].next=f[k].next,f[k].clear(),add(k),
pre=k;
}
}
bool find(int x)
{
int end=x%mod;
bool flag=0;
for(int k=first[end];k&&!flag;k=f[k].next)
if(f[k].val==x) flag=1;
return flag;
}
bool cmp(node a,node b)
{
if(pos[a.l]==pos[b.l]) return a.r<b.r;
return a.l<b.l;
}
void work()
{
for(int l=1,r=0,i=1;i<=m;i++)
{
while(r<e[i].r) r++,gethash(vi[r]);
while(r>e[i].r) del(vi[r]),r--;
while(l<e[i].l) del(vi[l]),l++;
while(l>e[i].l) l--,gethash(vi[l]);
ans[e[i].order]=find(e[i].x);
}
}
int main()
{
freopen("statistic.in","r",stdin);
freopen("statistic.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&vi[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++) scanf("%d %d %d",&e[i].l,&e[i].r,&e[i].x),e[i].order=i;
int sqr=sqrt(n);
for(int i=1;i<=n;i++) pos[i]=(i-1)/sqr+1;
std::sort(e+1,e+1+m,cmp);
for(int i=1;i<=n;i++) add(i);
work();
for(int i=1;i<=m;i++) printf("%d",ans[i]);
fclose(stdin);
fclose(stdout);
return 0;
}
做法二:nlognlogn
线段树套平衡树
时间:1.1s左右
#include<cstdio>
#include<cstring>
#include<cstdlib>
const int N=1e5+7;
int size;
struct node
{
int size,w,v,rnd,c[2];
}tr[N*20];
#define lson tr[k].c[0]
#define rson tr[k].c[1]
int rott[4*N];
int a[N];
int sum;
void update(int k)
{
tr[k].size=tr[lson].size+tr[rson].size+tr[k].w;
}
void rturn(int &k)
{
int t=tr[k].c[0];tr[k].c[0]=tr[t].c[1];tr[t].c[1]=k;
tr[t].size=tr[k].size;update(k);k=t;
}
void lturn(int &k)
{
int t=tr[k].c[1];tr[k].c[1]=tr[t].c[0];tr[t].c[0]=k;
tr[t].size=tr[k].size;update(k);k=t;
}
void insert(int &k,int num)
{
if(!k)
{
k=++size; tr[k].size=tr[k].w=1;tr[k].rnd=rand();tr[k].v=num;
return;
}
tr[k].size++;
if(num==tr[k].v) tr[k].w++;
else if(num<tr[k].v)
{
insert(lson,num);if(tr[lson].rnd<tr[k].rnd) rturn(k);
}
else
{
insert(rson,num);if(tr[rson].rnd<tr[k].rnd) lturn(k);
}
}
void build(int ro,int l,int r,int num,int x)
{
insert(rott[ro],num);
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) build(ro<<1,l,mid,num,x);
else build(ro<<1|1,mid+1,r,num,x);
}
int check(int k,int num)
{
if(sum>0)return 0;
if(!k) return 0;
if(num==tr[k].v) return tr[k].w;
else if(num<tr[k].v) return check(lson,num);
else return check(rson,num);
}
void query(int ro,int l,int r,int x,int y,int num)
{
if(sum>0) return;
if(x<=l&&r<=y)
{
sum+=check(rott[ro],num);
return;
}
int mid=(l+r)>>1;
if(x<=mid) query(ro<<1,l,mid,x,y,num);
if(y>mid) query(ro<<1^1,mid+1,r,x,y,num);
}
int main()
{
freopen("statistic.in","r",stdin);
freopen("statistic.out","w",stdout);
srand(5);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++)build(1,1,n,a[i],i);
int m;
int u,v,q;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
sum=0;
scanf("%d %d %d",&u,&v,&q),query(1,1,n,u,v,q);
printf("%d",sum>0?1:0);
}
fclose(stdin);
fclose(stdout);
return 0;
}
做法3:O(N)
把询问的端点放在1.....n上
然后扫的时候处理一下就行了
时间:0.05s左右
#include<cstdio>
#include<cstring>
const int N=1e5+7;
struct node
{
int tag,x,next,order;
}e[2*N];
struct edgt
{
int x,next;
}f[N];
const int mod=1e7+19;
int first[mod+52],last[mod+52];
int cnt;
void add(int u,int x,int order,int tag)
{
e[++cnt]=(node){tag,x,first[u],order};first[u]=cnt;
}
int tot;
int read()
{
int ans=0;char t=getchar();
while(t<'0'||t>'9') t=getchar();
while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar();
return ans;
}
int hash(int x)
{
int end=x%mod;
for(int k=last[end];k;k=f[k].next) if(f[k].x==x) return k;
f[++tot]=(edgt){x,last[end]};last[end]=tot;
return tot;
}
int sum[N],ans[N],a[N];
int find(int x)
{
int end=x%mod;
for(int k=last[end];k;k=f[k].next) if(f[k].x==x) return k;
return 0;
}
char pu[N];
int main()
{
freopen("statistic.in","r",stdin);
freopen("statistic.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) a[i]=read();
int m;
scanf("%d",&m);
int u,v,q;
for(int i=1;i<=m;i++)
{
u=read(),v=read(),q=read();
add(u-1,q,i,-1);
add(v,q,i,1);
}
for(int i=1;i<=n;i++)
{
int kkk=hash(a[i]);
sum[kkk]++;
for(int k=first[i];k;k=e[k].next)
{
int ttt=find(e[k].x);
ans[e[k].order]+=e[k].tag*sum[ttt];
}
}
for(int i=1;i<=m;i++) pu[i]=(ans[i]>0?1:0)+'0';
printf("%s",pu+1);
fclose(stdin);
fclose(stdout);
return 0;
}