luogu題解 P3709 【大爺的字符串題】
阿新 • • 發佈:2018-04-27
出現 出了 數組長度 其他 == pre har return 出現次數
- 題目鏈接:
https://www.luogu.org/problemnew/show/P3709
- 思路:
首先我是沒讀懂題目的,瀏覽了討論區的dalao發現才知道就是求區間眾數的出現次數。
然後肯定是用莫隊,具體怎麽寫莫隊其他題解都寫得很詳細,這裏不贅述.然後觀察數據範圍1e9肯定要離散化。
但是題解裏講離散化的不多,我就講一講我自己瞎搞的一個離散化方法
看到題解裏其他dalao都是什麽lower_bound或我看不懂的神仙操作。而蒟蒻我就瞎搞出了一個比較暴力的,也通俗易懂方法---開了兩個map.
第一個map al用來離散化,記錄元素是否出現過.
第二個map getrk顧名思義,用來離散化獲取每個數的排名.
dat[]用來記錄原字符串,num[]用來記錄去重後的數,即所有出現的元素
讀入字符串後將num[]從大到小排序,記錄每一個出現元素的排名,當然就是用getrk
接著就不管num[],我們遍歷一遍獲取原字符串中每個數的排名完成離散化.
由於開了map,常數比較大,開了O2跑了2000多ms,但是能過就行了
- 代碼:
// luogu-judger-enable-o2 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cctype> #include <map> #include <cmath> using namespace std; const int maxn=200005; map <int,bool>al; map <int,int>getrk; struct Ask{ int l,r,id,x; }ask[maxn]; int num[maxn],dat[maxn],rk[maxn]; int belong[maxn],block; int N,n=0,m; int a[maxn],cnt[maxn]; int ans[maxn],anss=0; template<class T>inline void read(T &x){ x=0;int ne=0;char c; while(!isdigit(c=getchar()))ne=c==‘-‘; x=c-48; while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48; x=ne?-x:x; return ; } inline bool cmp0(const int&x,const int&y){ return x>y; } inline bool cmp2(const Ask &x,const Ask &y){ return belong[x.l]^belong[y.l]?belong[x.l]<belong[y.l]:belong[x.l]&1?x.r<y.r:x.r>y.r; } inline void init() { int x; read(N),read(m); block=N/sqrt(m*2/3); n=0; for(register int i=1;i<=N;i++){//N是原字符串長度 read(x); dat[i]=x; if(al[x]==0){//去重 num[++n]=x;//n是去重後num[]數組長度 al[x]=1; } belong[i]=(i-1)/block+1; } sort(num+1,num+1+n,cmp0); for(register int i=1;i<=n;i++){ getrk[num[i]]=i; // belong[i]=(i-1)/block+1; } for(register int i=1;i<=N;i++){ rk[i]=getrk[dat[i]]; } //sort(num+1,num+1+n,cmp1); for(register int i=1;i<=m;i++){ read(ask[i].l),read(ask[i].r); ask[i].id=i; } sort(ask+1,ask+1+m,cmp2); return; } inline void add(int x){ int now=rk[x]; if(anss==a[now])anss++; cnt[a[now]]--; a[now]++; cnt[a[now]]++; return; } inline void sub(int x){ int now=rk[x]; if(anss==a[now]&&cnt[a[now]]==1)anss--; cnt[a[now]]--; a[now]--; cnt[a[now]]++; return; } inline void solve() { int l=1,r=0,ll,rr; cnt[0]=n; for(register int i=1;i<=m;i++){ ll=ask[i].l,rr=ask[i].r; while(r<rr)add(++r); while(r>rr)sub(r),r--; while(l<ll)sub(l),l++; while(l>ll)add(--l); ans[ask[i].id]=anss; } for(register int i=1;i<=m;i++){ printf("-%d\n",ans[i]); } return ; } int main() { init(); solve(); return 0; }
luogu題解 P3709 【大爺的字符串題】