主席树 STL+二分【p3939】数颜色
Description
小 C 的兔子不是雪白的,而是五彩缤纷的。每只兔子都有一种颜色,不同的兔子可能有 相同的颜色。小 C 把她标号从 \(1\) 到 \(n\) 的 \(n\) 只兔子排成长长的一排,来给他们喂胡萝卜吃。 排列完成后,第 \(i\) 只兔子的颜色是 \(a_i\)。
俗话说得好,“萝卜青菜,各有所爱”。小 C 发现,不同颜色的兔子可能有对胡萝卜的 不同偏好。比如,银色的兔子最喜欢吃金色的胡萝卜,金色的兔子更喜欢吃胡萝卜叶子,而 绿色的兔子却喜欢吃酸一点的胡萝卜……为了满足兔子们的要求,小 C 十分苦恼。所以,为 了使得胡萝卜喂得更加准确,小 C 想知道在区间 \([l_j,r_j]\) 里有多少只颜色为 \(c_j\) 的兔子。
不过,因为小 C 的兔子们都十分地活跃,它们不是很愿意待在一个固定的位置;与此同 时,小 C 也在根据她知道的信息来给兔子们调整位置。所以,有时编号为 \(x_j\) 和 \(x_j+1\) 的两 只兔子会交换位置。 小 C 被这一系列麻烦事给难住了。你能帮帮她吗?
Input
从标准输入中读入数据。 输入第 1 行两个正整数 \(n,m\)。
输入第 2 行 \(n\) 个正整数,第 \(i\) 个数表示第 \(i\) 只兔子的颜色 \(a_i\)。
输入接下来 \(m\) 行,每行为以下两种中的一种:
- “\(1\ l_j\ r_j\ c_j\)” :询问在区间 \([l_j,r_j]\) 里有多少只颜色为 \(c_j\) 的兔子;
- “\(2\ x_j\)”: \(x_j\) 和 \(x_j+1\) 两只兔子交换了位置。
Output
输出到标准输出中。
对于每个 1 操作,输出一行一个正整数,表示你对于这个询问的答案。
woc,写了主席树.结果T了4个点,尝试大力卡常也没过QAQ.
主席树(80pts)
对于颜色建树.
考虑到主席树的性质是维护前缀.
所以我们可以直接查询,可以直接修改.
修改操作是这样的
可能叫build会比较奇怪
build(root[l],root[l],1,300000,col[l],-1); build(root[l],root[l],1,300000,col[l+1],1);
这个应该不是很难理解.(如果你会主席树的话.)
不理解的话,再想想主席树的性质好了.
80pts代码
#include<cstdio> #include<iostream> #include<algorithm> #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } void print(int x) { if(x<0) { putchar('-'); x=-x; } if(x>9)print(x/10); putchar(x%10+'0'); } int sum[20000000],lson[20000000],rson[20000000],root[20000000]; int cnt,n,m,col[500003]; void build(int lastroot,int &nowroot,int l,int r,int pos,int k) { nowroot=++cnt; sum[nowroot]=sum[lastroot]+k; lson[nowroot]=lson[lastroot]; rson[nowroot]=rson[lastroot]; if(l==r)return; int mid=(l+r)>>1; if(pos<=mid) build(lson[lastroot],lson[nowroot],l,mid,pos,k); else build(rson[lastroot],rson[nowroot],mid+1,r,pos,k); } int query(int lastroot,int nowroot,int l,int r,int pos) { if(l==r)return sum[nowroot]-sum[lastroot]; int mid=(l+r)>>1; if(pos<=mid) return query(lson[lastroot],lson[nowroot],l,mid,pos); else return query(rson[lastroot],rson[nowroot],mid+1,r,pos); } int main() { in(n),in(m); for(R int i=1;i<=n;i++) { in(col[i]); build(root[i-1],root[i],1,300000,col[i],1); } for(R int i=1,opt,l,r,k;i<=m;i++) { in(opt); if(opt==1) { in(l),in(r),in(k); print(query(root[l-1],root[r],1,300000,k)); putchar('\n'); } else { in(l); build(root[l],root[l],1,300000,col[l],-1); build(root[l],root[l],1,300000,col[l+1],1); swap(col[l],col[l+1]); } } }
Vector+二分 (100pts)
用\(Vector\)记录每个颜色出现的位置,然后二分.
代码
#include<vector> #include<cstdio> #include<iostream> #include<algorithm> #define R register #define maxn 300010 #define inf 2147483640 using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } vector < int > col[maxn] ; int n , init[maxn] , m ; inline void work(int l , int r , int x) { int posl = lower_bound(col[x].begin() , col[x].end() , l) - col[x].begin() ; int posr = upper_bound(col[x].begin() , col[x].end() , r) - col[x].begin() - 1 ; printf("%d",posr-posl+1); } inline void work(int x) { int l = x , r = x + 1 ; if(init[l] == init[r]) return ; int posl = lower_bound(col[init[l]].begin() , col[init[l]].end() , l) - col[init[l]].begin() ; int posr = lower_bound(col[init[r]].begin() , col[init[r]].end() , r) - col[init[r]].begin() ; col[init[l]][posl] ++ ; col[init[r]][posr] -- ; swap(init[l] , init[r]) ; } int main() { in(n),in(m) ; int opt , l , r , x ; for(int i = 1 ; i <= n ; ++i) in(init[i]),col[init[i]].push_back(i); for(int i = 1 ; i <= m ; ++i) { in(opt); if(opt == 1) in(l),in(r),in(x) , work(l , r , x) ; else in(x),work(x) ; } return 0 ; }
- 数颜色 (二分查找 主席树)
- STL中的二分查找——lower_bound 、upper_bound 、binary_search
- STL之二分查找(binary_search(),lower_bound(),upper_bound() )
- bzoj2653 middle(主席树+二分)
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码【A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博弈,J,差分dp,K,二分+排序,L,矩阵快速幂,M,线段树区间更新+Lazy思想,N,超级快速幂+扩展欧里几德,O,BFS】
- 【 STL之二分查找 (Binary search in STL)】
- 【POJ 2104/HDU 2665】K-th Number【整体二分/主席树】
- SSL-1135 二分查找【二分,STL_algorithm,hash】
- [BZOJ4556][Tjoi2016&Heoi2016]字符串(后缀数组+二分+st表+主席树)
- BZOJ5011 [JXOI2017]颜色 【线段树 + 主席树】
- HDU 5915 (二分 主席树)
- [BZOJ1208][[HNOI2004]宠物收养所][STL set+二分]
- 求第k大连续区间和/第k大子序列和 - 二分+树状数组+前缀和(或主席树+堆)
- STL之二分查找 (Binary search in STL)
- Hrbust 2054 Boring Counting (主席树+二分)
- hdu 4417 Super Mario (主席树+二分)
- bzoj 4556: [Tjoi2016&Heoi2016]字符串 (主席树+二分+后缀数组+ST表||后缀自动机+线段树合并+LCA)
- STL中二分查找函数
- 第四届 山东省ACM Boring Counting(划分树+二分 主席树待整理)
- STL之二分查找(binary_search(),lower_bound(),upper_bound() )