HDU 4358 Boring Counting ★★(2012 Multi-University Training Contest 6)
生活随笔
收集整理的這篇文章主要介紹了
HDU 4358 Boring Counting ★★(2012 Multi-University Training Contest 6)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
問題抽象:區(qū)間內(nèi)恰好出現(xiàn)K次的數(shù)的個數(shù)。 ------------------------------------------------------------------ UESTC出的題就是神啊T_T。。。一開始想了個函數(shù)式線段樹方法后來發(fā)現(xiàn)錯了=。=,然后也沒什么思路,就是找著官方題解的方法做的。 思路: 題解說的用樹狀數(shù)組,這里當然也可以用線段樹維護,和上面一樣,線段樹第j個數(shù)表示區(qū)間[j, i]內(nèi)出現(xiàn)k次的數(shù)有多少個,然后像題解一樣維護即可。(這種維護方法值得好好研究&&學習呀~) 代碼中也有比較詳細的注釋: #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)using namespace std;
const int maxn = 100100;int id,n,K;
int ans[maxn];
int w[maxn],wb[maxn];
int vis[maxn];
int a[maxn]; //線性權值
int l[maxn],r[maxn]; //線性區(qū)間
vector v[maxn]; //邊表
vector pos[maxn]; //記錄某數(shù)出現(xiàn)的位置
int num[maxn]; //記錄某個數(shù)出現(xiàn)多少次了
map M; //離散化
int mtot;struct ANS
{int l,r;int id;
}Q[maxn];bool cmp(ANS a1, ANS a2)
{return a1.r ::iterator vp;if (v[x].size())for (vp = v[x].begin(); vp != v[x].end(); vp ++)dfs(*vp);r[x] = id;}
}int sum[maxn<<2],add[maxn<<2];
void build(int l,int r,int rt)
{sum[rt] = 0;add[rt] = 0;if (l == r) return ;int mid = MID(l,r);build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);
}
void pushdown(int rt,int w)
{if (add[rt]){add[rt<<1] += add[rt];add[rt<<1|1] += add[rt];sum[rt<<1] += add[rt] * (w - (w >> 1));sum[rt<<1|1] += add[rt] * (w >> 1);add[rt] = 0;}
}
void update(int s,int t,int v,int l,int r,int rt)
{if (s <= l && r <= t){sum[rt] += v * (r - l + 1);add[rt] += v;return ;}pushdown(rt, r-l+1);int mid = MID(l,r);if (s <= mid) update(s,t,v,l,mid,rt<<1);if (mid < t) update(s,t,v,mid+1,r,rt<<1|1);
}
int query(int p,int l,int r,int rt)
{if (l == p && r == p){return sum[rt];}pushdown(rt,r-l+1);int mid = MID(l,r);if (p <= mid) return query(p,l,mid,rt<<1);else return query(p,mid+1,r,rt<<1|1);
}
int main()
{//freopen("data.txt","r+",stdin);int tt,caseo = 1;scanf("%d",&tt);while(tt--){//Initializemtot = id = 0;memset(v,0,sizeof(v));memset(vis,0,sizeof(vis));memset(pos,0,sizeof(pos));memset(num,0,sizeof(num));//inputprintf("Case #%d:\n",caseo ++);scanf("%d%d",&n,&K);for (int i = 1; i <= n; i ++)scanf("%d",&w[i]);for (int i = 1; i < n; i ++){int a,b;scanf("%d%d",&a,&b);v[a].push_back(b); //邊表}//樹形結構轉線性結構dfs(1);M.clear();//權值離散化for (int i = 1; i <= n; i ++)if (!M[a[i]]) M[a[i]] = ++ mtot;int q;scanf("%d",&q);for (int i = 0; i < q; i ++){int p;scanf("%d",&p);Q[i].l = l[p];Q[i].r = r[p];Q[i].id = i;}sort(Q,Q+q,cmp);int pt = 0;build(1,n,1);for (int i = 1; i <= n; i ++){pos[M[a[i]]].push_back(i);num[M[a[i]]] ++;if (num[M[a[i]]] >= K)if (num[M[a[i]]] == K)update(1,pos[M[a[i]]][0],1,1,n,1);else{int ss = (num[M[a[i]]] - K <= 2)?1:(num[M[a[i]]] - K - 2);update(ss,pos[M[a[i]]][num[M[a[i]]]-K-1],-1,1,n,1);update(pos[M[a[i]]][num[M[a[i]]]-K-1]+1,pos[M[a[i]]][num[M[a[i]]]-K],1,1,n,1);}else;while(pt < q && Q[pt].r == i){ans[Q[pt].id] = query(Q[pt].l,1,n,1);pt ++;}}for (int i = 0; i < q; i ++)printf("%d\n",ans[i]);if (tt) printf("\n");}return 0;
}
轉載于:https://www.cnblogs.com/AbandonZHANG/archive/2012/11/15/4114165.html
總結
以上是生活随笔為你收集整理的HDU 4358 Boring Counting ★★(2012 Multi-University Training Contest 6)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 115网盘提取码是什么怎么用
- 下一篇: 模块化加载时断点调试没反应,进入不了断点