日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P1972 [SDOI2009]HH的项链

發(fā)布時間:2023/12/3 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P1972 [SDOI2009]HH的项链 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

P1972 [SDOI2009]HH的項鏈

題意:

給你一個序列,問這個序列中的種類數(shù)
n,m,ai<=1e6

題解:

三個方法:莫隊(會超時),樹狀數(shù)組,主席樹(會超時)

莫隊就是裸題,不講了,復(fù)雜度O(n*sqrt(n))

樹狀數(shù)組:
對于若干個區(qū)間[l,r],如果他們的r都相等,那么項鏈中出現(xiàn)的同一個數(shù)字,一定只關(guān)心最右邊的那一個。
比如:1 3 4 5 1
對于r=5的所有詢問,第一個位置上的1是沒有價值的,因為第五個位置已經(jīng)出現(xiàn)1,也就是對于所有查詢[L,5]區(qū)間來說,如果第一個1被算,那么它完全可以用第5個1來代替
因此,我們對所有詢問按照r來排序,然后維護(hù)一個樹狀數(shù)組。
樹狀數(shù)組的用途:
對于序列:1 2 1 3
我們用pre[i]來表示上一此出現(xiàn)i的位置
對于第一個1,insert(1,1),此時樹狀數(shù)組表示的每個數(shù)有1 0 0 0
對于第二個2,insert(2,1),此時1 1 0 0
對于第三個1,因為之前出現(xiàn)過1,所以將之前1的位置刪掉,insert(1,-1),然后再把當(dāng)前1加入insert(3,1).此時就是0 1 1 0
詢問[2,3],就是sum(3)-sum(2-1)=2

主席樹做法:
對于每個點(diǎn),我們用nex表示這個點(diǎn)之后最近的顏色相同的點(diǎn)的位置,如果沒有就設(shè)為n+1.
對于區(qū)間詢問l~r之間的種類,其實就是求滿足(l<=i<=r&&nex[i]>r)的個數(shù),因為如果某個點(diǎn)的next已近超出了這個區(qū)間的范圍,就說明這個點(diǎn)對答案產(chǎn)生貢獻(xiàn)了(其實和樹狀數(shù)組思想是一樣的,相同顏色只考慮離r最近的)
這樣問題就變成在區(qū)間l~r之間權(quán)值大于r的個數(shù)
復(fù)雜度是O(mlogn),也會超時

代碼:

莫隊

// Problem: P1972 [SDOI2009]HH的項鏈 // Contest: Luogu // URL: https://www.luogu.com.cn/problem/P1972 // Memory Limit: 512 MB // Time Limit: 2000 ms // Data:2021-08-12 09:19:00 // By Jozky#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; template <typename T> inline void read(T& x) {T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f; } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } int n, m; const int maxn= 3e6 + 9; int a[maxn]; int block; struct node {int l, r;int id;bool operator<(const node& x) const{if (l / block != x.l / block)return l < x.l;if ((l / block) & 1)return r < x.r; // 注意這里和下面一行不能寫小于(大于)等于,否則會出錯(詳見下面的小細(xì)節(jié))return r > x.r;} } q[maxn]; int ans[maxn]; int vis[maxn]; int tot= 0; void add(int x) {vis[a[x]]++;if (vis[a[x]] == 1)tot++; } void del(int x) {vis[a[x]]--;if (vis[a[x]] == 0)tot--; }// bool cmp(node a, node b) // { // if (a.r / block == b.r / block) // return a.l < b.l; // return a.r < b.r; // } int main() {//rd_test();read(n);block= sqrt(n);for (int i= 1; i <= n; i++)read(a[i]);read(m);for (int i= 1; i <= m; i++) {read(q[i].l);read(q[i].r);q[i].id= i;}sort(q + 1, q + 1 + m);int l= 1, r= 0;for (int i= 1; i <= m; i++) {int L= q[i].l, R= q[i].r;while (l < L)del(l++);while (l > L)add(--l);while (r < R)add(++r);while (r > R)del(r--);ans[q[i].id]= tot;}for (int i= 1; i <= m; i++) {printf("%d\n", ans[i]);}return 0;//Time_test(); }

樹狀數(shù)組

#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; template <typename T> inline void read(T& x) {T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f; } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn= 2e6; int a[maxn]; struct node {int l, r;int id; } q[maxn]; int sum[maxn]; int ans[maxn]; int n; int vis[maxn]; bool cmp(node a, node b) {return a.r < b.r; } int lowbit(int x) {return x & (-x); } void add(int pos, int x) {for (int i= pos; i <= n; i+= lowbit(i)) {sum[i]+= x;} } int query(int pos) {int ans= 0;for (int i= pos; i >= 1; i-= lowbit(i)) {ans+= sum[i];}return ans; } int query(int l, int r) {return query(r) - query(l - 1); } int main() {//rd_test();read(n);for (int i= 1; i <= n; i++)read(a[i]);int m;read(m);for (int i= 1; i <= m; i++)read(q[i].l), read(q[i].r), q[i].id= i;sort(q + 1, q + 1 + m, cmp);int beg= 1;for (int i= 1; i <= m; i++) {for (int j= beg; j <= q[i].r; j++) {if (vis[a[j]])add(vis[a[j]], -1);add(j, 1);vis[a[j]]= j;}beg= q[i].r + 1;ans[q[i].id]= query(q[i].l, q[i].r);}for (int i= 1; i <= m; i++)printf("%d\n", ans[i]);return 0;//Time_test(); }

主席樹

#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; template <typename T> inline void read(T& x) {T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f; } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn= 2e6 + 9; int rs[maxn], ls[maxn]; int sum[maxn]; int n; int a[maxn]; int rt[maxn]; int tot= 0; int vis[maxn], nex[maxn]; void build(int& o, int l, int r) {o= ++tot;sum[o]= 0;if (l == r)return;int mid= (l + r) >> 1;build(ls[o], l, mid);build(rs[o], mid + 1, r); } void update(int& o, int l, int r, int nex, int p) {o= ++tot;ls[o]= ls[nex];rs[o]= rs[nex];sum[o]= sum[nex] + 1;if (l == r)return;int mid= (l + r) >> 1;if (p <= mid)update(ls[o], l, mid, ls[nex], p);elseupdate(rs[o], mid + 1, r, rs[nex], p); } int query(int u, int v, int l, int r, int k) {int mid= (l + r) >> 1;int ans= 0;if (l == r) {return sum[v] - sum[u];}if (k <= mid) {int x= sum[rs[v]] - sum[rs[u]];ans+= query(ls[u], ls[v], l, mid, k) + x;}elseans+= query(rs[u], rs[v], mid + 1, r, k);return ans; } int main() {//rd_test();read(n);for (int i= 1; i <= n; i++) {read(a[i]);if (vis[a[i]])nex[vis[a[i]]]= i;vis[a[i]]= i;}for (int i= 1; i <= n; i++) {if (!nex[i])nex[i]= n + 1;}build(rt[0], 1, n + 1);for (int i= 1; i <= n; i++) {int p= nex[i];update(rt[i], 1, n + 1, rt[i - 1], p);}int m;read(m);while (m--) {int l, r;read(l), read(r);printf("%d\n", query(rt[l - 1], rt[r], 1, n + 1, r + 1));}//Time_test(); }

總結(jié)

以上是生活随笔為你收集整理的P1972 [SDOI2009]HH的项链的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。