[BZOJ3236]作业
作业
题目描述
输入格式
输出格式
样例
数据范围与提示
真难受,打了两节半晚课,一开始连点思路都没有,颓题解发现全世界的题解都是"莫队+分块/树状数组"就结束了,一气之下颓了代码,我不是人,看了半天才研究明白代码(?),这也不是个多难的题啊,我更不是人了,结果发现颓的代码是个WA0的?一脸懵逼,我今天招惹谁了?mmp,我发现我最近每天晚上都要吐槽一大堆,最近运势不太对,讲题吧,明天该考试了,期待rp++
我怕我写个莫队+树状数组然后贴个代码会rp--,所以说一说吧,顺便复习一下树状数组(我发现我都忘光了),后面的pa大哥现在在说这是道水题,我???又是一脸懵逼,不扯了
其实这道题说是莫队其实挺明显的,查询区间还不用修改,莫队很优秀啊,不过关于那个大于等于a,小于等于b,其实我没想到怎么处理,后来颓完代码,觉得,树状数组真是个优秀的办法,单点修改,区间查询,莫队+树状数组优秀啊,我们来想想树状数组要维护些什么,偷偷告诉你,要两个树状数组哦,显然,问题既然是两个,那就维护那两个问题呗,一个维护区间中出现过多少个不同的数,一个维护区间中一共多少个数,这样的话,我们用莫队进行++--的操作,然后对于每个询问中的[a,b]进行区间查询,优秀的不的了,然后树状数组一波搞,然后就可以A了,不过关于出现了多少个不同的数值可不能随随便便搞,他只能是当你区间中只有一个这个数,你把它搞掉了,或者没有这个数,你搞进来了一个,才可以修改这个答案,一共有多少个数,每次移动区间都修改就对了,emm,大概真的就是个莫队的模板+树状数组的模板,还是我太弱了,不过这题分块也可以,有兴趣的自己试一试,说不定线段树也没毛病呢
1 //数值的个数就是只算一遍 2 //数的个数就是重复的也算 3 #include<cmath> 4 #include<cstdio> 5 #include<iostream> 6 #include<algorithm> 7 #define maxn 100010 8 #define maxm 1000100 9 using namespace std; 10 struct node{ 11 int l,r,a,b,bh,sz,s; 12 }q[maxm]; 13 int n,m,kc; 14 int a[maxn],ss[maxn],SZ[maxm],S[maxm],cs[maxm]; 15 int lowbit(int x) 16 { 17 return x&(-x); 18 } 19 bool cmp(const node &a,const node &b) 20 { 21 return ss[a.l]==ss[b.l]?a.r<b.r:a.l<b.l; 22 } 23 bool cmpp(const node &a,const node &b) 24 { 25 return a.bh<b.bh; 26 } 27 void add(int x,int c) 28 { 29 for(int i=x;i<=n;i+=lowbit(i)) S[i]+=c; 30 } 31 void addd(int x,int c) 32 { 33 for(int i=x;i<=n;i+=lowbit(i)) SZ[i]+=c; 34 } 35 int sum(int x) 36 { 37 int c=0; 38 for(int i=x;i;i-=lowbit(i)) c+=S[i]; 39 return c; 40 } 41 int summ(int x) 42 { 43 int c=0; 44 for(int i=x;i;i-=lowbit(i)) c+=SZ[i]; 45 return c; 46 } 47 void upd(int x,int c) 48 { 49 if(c==1&&++cs[a[x]]==1) addd(a[x],c); 50 if(c==-1&&--cs[a[x]]==0) addd(a[x],c); 51 add(a[x],c); 52 } 53 int main() 54 { 55 scanf("%d%d",&n,&m); kc=sqrt(n); 56 for(int i=1;i<=n;++i) {scanf("%d",&a[i]); ss[i]=i/kc+1;} 57 for(int i=1;i<=m;++i) 58 { 59 scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b); 60 q[i].bh=i; 61 } 62 sort(q+1,q+m+1,cmp); 63 int z=1,y=0; 64 for(int i=1;i<=m;++i) 65 { 66 while(z<q[i].l) upd(z++,-1); 67 while(z>q[i].l) upd(--z,1); 68 while(y<q[i].r) upd(++y,1); 69 while(y>q[i].r) upd(y--,-1); 70 q[i].s=sum(q[i].b)-sum(q[i].a-1); 71 q[i].sz=summ(q[i].b)-summ(q[i].a-1); 72 } 73 sort(q+1,q+m+1,cmpp); 74 for(int i=1;i<=m;++i) printf("%d %d\n",q[i].s,q[i].sz); 75 return 0; 76 }