2018.07.07 洛谷 P3939 数颜色(主席树)

xiaoxiao2021-02-28  45

P3939 数颜色 题目背景 大样例下发链接:http://pan.baidu.com/s/1c0LbQ2 密码:jigg

题目描述 小 C 的兔子不是雪白的,而是五彩缤纷的。每只兔子都有一种颜色,不同的兔子可能有 相同的颜色。小 C 把她标号从 1 到 n n nn 只兔子排成长长的一排,来给他们喂胡萝卜吃。 排列完成后,第 ii 只兔子的颜色是 4ai 4 a i 。俗话说得好,“萝卜青菜,各有所爱”。小 C 发现,不同颜色的兔子可能有对胡萝卜的 不同偏好。比如,银色的兔子最喜欢吃金色的胡萝卜,金色的兔子更喜欢吃胡萝卜叶子,而 绿色的兔子却喜欢吃酸一点的胡萝卜……为了满足兔子们的要求,小 C 十分苦恼。所以,为 了使得胡萝卜喂得更加准确,小 C 想知道在区间 [lj,rj] [ l j , r j ] 里有多少只颜色为 cj c j 的兔子。 不过,因为小 C 的兔子们都十分地活跃,它们不是很愿意待在一个固定的位置;与此同 时,小 C 也在根据她知道的信息来给兔子们调整位置。所以,有时编号为 xj x j xj+1 x j + 1 的两 只兔子会交换位置。 小 C 被这一系列麻烦事给难住了。你能帮帮她吗? 输入输出格式 输入格式: 从标准输入中读入数据。 输入第 1 行两个正整数 n n , mm 。 输入第 2 行 n n 个正整数,第 ii 个数表示第 i i 只兔子的颜色 aiai。 输入接下来 mm 行,每行为以下两种中的一种: “ 1 lj rj cj1 1   l j   r j   c j 1 ” :询问在区间 [lj,rj] [ l j , r j ] 里有多少只颜色为 cj c j ​ 的兔子; “ 2 xj 2   x j ”: xj x j xj+1 x j + 1 两只兔子交换了位置。 输出格式: 输出到标准输出中。 对于每个 1 操作,输出一行一个正整数,表示你对于这个询问的答案。

输入输出样例 输入样例#1: 6 5 1 2 3 2 3 3 1 1 3 2 1 4 6 3 2 3 1 1 3 2 1 4 6 3 输出样例#1: 1 2 2 3 说明 【样例 1 说明】

前两个 1 操作和后两个 1 操作对应相同;在第三次的 2 操作后,3 号兔子和 4 号兔子

交换了位置,序列变为 1 2 2 3 3 3。

【数据范围与约定】

子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解 决一部分测试数据。 对于所有测试点,有 1lj<rjn 1 ≤ l j < r j ≤ n , 1xj<n 1 ≤ x j < n 每个测试点的数据规模及特点如下表: 特殊性质 1:保证对于所有操作 1,有 |rjlj|20 | r j − l j | ≤ 20 |rjlj|n20 | r j − l j | ≤ n − 20

特殊性质 2:保证不会有两只相同颜色的兔子。

好吧这又是一道水题,我可能是最近做数据结构做傻了,搞得连 vector v e c t o r +二分这种技巧都搞忘了。没错,这道题标解就是 vector v e c t o r +二分,但看到区间统计数的个数怎能不让人想到主席树呢?于是就有大佬对每种颜色建主席树跑过,但在我看来,这种方法和 vector v e c t o r +二分的本质思想并没有区别,因此我另辟蹊径,自己 yy y y 了一种做法(下来看了题解之后才发现自己又 zz z z 了)。好吧我们对每个位置建一个主席树,然后主席树就成了前缀的形式,于是我们修改就与后面的前缀无关(因为从 xj+1 x j + 1 n n 这些位置的每个数的权值仍然是不变的,这样的话操作2就变成了删除和插入操作的组合,不过貌似这样写会被卡常,本蒟蒻被卡了多次后乱改常数终于过了。事实证明switchswitch的确快过 if i f 啊)

代码如下:

#include<bits/stdc++.h> #define N 300005 using namespace std; struct Node{int l,r,sum;}T[N*70]; int cnt=0,rt[N*70],n,m,col[N],siz=0; inline void update(int &p,int last,int l,int r,int v,int tmp){ p=++cnt,T[p].l=T[last].l,T[p].r=T[last].r; T[p].sum=T[last].sum+tmp; if(l==r)return; int mid=l+r>>1; if(v<=mid)update(T[p].l,T[last].l,l,mid,v,tmp); else update(T[p].r,T[last].r,mid+1,r,v,tmp); } inline int read(){ int ans=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); return ans; } inline int query(int p,int l,int r,int v){ if(l==r)return T[p].sum; int mid=l+r>>1; if(v<=mid)return query(T[p].l,l,mid,v); else return query(T[p].r,mid+1,r,v); } int main(){ n=read(),m=read(); for(int i=1;i<=n;++i)update(rt[i],rt[i-1],1,300000,col[i]=read(),1); while(m--){ int op=read(),l=read(); switch(op){ case 1:{ int r=read(),c=read(); printf("%d\n",query(rt[r],1,300000,c)-query(rt[l-1],1,300000,c)); break; } default:{ update(rt[l],rt[l],1,300000,col[l],-1); update(rt[l],rt[l],1,300000,col[l+1],1); col[l]^=col[l+1],col[l+1]^=col[l],col[l]^=col[l+1]; break; } } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-2620125.html

最新回复(0)