题:https://www.nowcoder.com/acm/contest/139/J
思路:把原序列复制一份,两个序列连接在一起,每次查询 l 到 r+n区间有多少种数,,主席树被卡。莫队也被卡。给出AC代码
树状数组维护才是正解!!
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7;
int block,cnt[1000007],a[N],res[N],ans;
namespace fastIO {
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
struct node{
int l,r,id;
}q[N];
bool cmp(node a,node b)
{
return a.l/block!=b.l/block?a.l/block<b.l/block:a.r<b.r;
}
void update(int p,int val)
{
cnt[a[p]]+=val;
if(cnt[a[p]]==1&&val==1)ans++;
if(cnt[a[p]]==0&&val==-1)ans--;
// printf("fuck %d %d %d\n",cnt[a[p]],ans,val);
}
int main()
{
int n,m;
while(read(n),read(m),!IOerror){
block=sqrt(n);
memset(cnt,0,sizeof(cnt));
memset(res,0,sizeof(res));
for(int i=1;i<=n;i++){
// scanf("%d",&a[i]);
read(a[i]);
a[i+n]=a[i];
}
for(int i=1;i<=m;i++){
int A,B;
read(A),read(B);
// scanf("%d%d",&A,&B);
q[i].l=B;q[i].r=A+n;
// printf("test %d %d\n",q[i].l,q[i].r);
q[i].id=i;
}
n*=2;
sort(q+1,q+1+m,cmp);
ans=0;
// printf("test\n");
for(int i=1,l=1,r=0;i<=m;i++){
for(;r<q[i].r;r++)
update(r+1,1);
for(;r>q[i].r;r--)
update(r,-1);
for(;l<q[i].l;l++)
update(l,-1);
for(;l>q[i].l;l--)
update(l-1,1);
// printf("test %d %d ans === %d\n",q[i].l,q[i].r,ans);
res[q[i].id]=ans;
}
for(int i=1;i<=m;i++){
printf("%d\n",res[i]);
}
}
}
#include <bits/stdc++.h>
using namespace std;
#define met(a,b) memset(a,b,sizeof a)
const int N=2e5+50;
struct node {
int lson,rson;
int cnt;
};
node T[N*40];
int root[N],tot;
int sa[N];
int arr[N];
int last_pos[N];
inline void init() {
met(root,0);met(last_pos,0);
tot=0;
T[0].cnt=T[0].lson=T[0].rson=0;
}
inline void update(int &cur,int ori,int l,int r,int pos,int flag) {
cur=++tot;
T[cur]=T[ori];
T[cur].cnt+=flag;
if(l==r)
return ;
int mid=(l+r)/2;
if(pos<=mid)
update(T[cur].lson,T[ori].lson,l,mid,pos,flag);
else
update(T[cur].rson,T[ori].rson,mid+1,r,pos,flag);
}
inline int query(int S,int E,int l,int r,int x,int y) {
if(x<=l&&r<=y)
return T[E].cnt-T[S].cnt;
else {
int mid=(l+r)>>1;
if(y<=mid)
return query(T[S].lson,T[E].lson,l,mid,x,y);
else if(x>mid)
return query(T[S].rson,T[E].rson,mid+1,r,x,y);
else
return query(T[S].lson,T[E].lson,l,mid,x,mid)+query(T[S].rson,T[E].rson,mid+1,r,mid+1,y);
}
}
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q)){
init();
vector<int>pos;
for(int i=1; i<=n; ++i) {
scanf("%d",&arr[i]);
arr[i+n]=arr[i];
pos.push_back(arr[i]);
// sa[i]=arr[i];sa[i+n]=arr[i+n];
}
n*=2;
// printf("test %d\n",n);
sort(pos.begin(),pos.end());
pos.erase(unique(pos.begin(),pos.end()),pos.end());
int temp_rt=0;
for(int i=1;i<=n;++i){
arr[i]=lower_bound(pos.begin(),pos.end(),arr[i])-pos.begin()+1;
// arr[i]=getid(arr[i]);
// printf("test %d\n",last_pos[arr[i]]);
if(!last_pos[arr[i]]) {
update(root[i],root[i-1],1,n,i,1);
last_pos[arr[i]]=i;
}
else{
update(temp_rt,root[i-1],1,n,last_pos[arr[i]],-1);
update(root[i],temp_rt,1,n,i,1);
// update(root[i],root[i-1],1,n,i,1);
last_pos[arr[i]]=i;
}
}
while(q--){
int A,B;
scanf("%d%d",&A,&B);
if(A<B){
int l=B,r=A+n/2;
printf("%d\n",query(root[l-1],root[r],1,n,l,r));
}
else{
printf("%d\n",query(root[0],root[n],1,n,1,n));
}
// printf("test sum:%d l1:%d l2:%d r-1==%d l-1==%d l==%d r==%d\n",sum,l1,l2,query(1,r-1),query(1,l-1),query(l,n),query(r,n));
// printf("%d\n",ans);
}
}
return 0;
}