程序员人生 网站导航

hdu5212 Code 莫队算法

栏目:互联网时间:2015-05-19 08:09:14
这道题需要1些莫队算法的知识 定义记号f(A,B)表示询问区间A,B时的答案 用记号+表示集合的并 利用莫队算法我们可以计算出任意f(A,A)的值 无妨假定A=[l1,r1],B=[l2,r2],C=[r1+1,l2?1] 容易知道f(A,B)=f(A+B+C,A+B+C)+f(C,C)?f(A+C,A+C)?f(C+B,C+B) 因此1个询问被拆成4个可以用莫队算法做的询问 总的时间复杂度为O(msqrt(n))
(以上是官方题解)
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> using namespace std; typedef long long LL; const int N = 30000*4 + 10; int pos[N]; struct pp{     int l,r,id;     int ans; }p[N]; int cmp(pp a,pp b){     if(pos[a.l]==pos[b.l]) return a.r < b.r;     return a.l < b.l; } int cmp2(pp a,pp b){     return a.id < b.id; } struct que{     int l1,l2,r1,r2; }q[N]; int block,n,k,m,num; int a[N],cnt[N],answer; LL x; map<LL,int> mm; void update(int x,int v){     int val = k - a[x];     if(val <= 0) return ;     answer += cnt[val]*v;     cnt[a[x]] += v; } void solve(){     int l,r;     answer = 0;     for(int i=1,l=1,r=0;i<=num;i++){//按块进行更新         for(;r<p[i].r;r++)             update(r+1,1);         for(;r>p[i].r;r--)             update(r,⑴);         for(;l<p[i].l;l++)             update(l,⑴);         for(;l>p[i].l;l--)             update(l⑴,1);         p[i].ans = answer;     } } int main(){     while(scanf("%d",&n)!=EOF){         mm.clear();         num = 0;         block = (int)sqrt(n)+1;         for(int i=1;i<=n;i++) pos[i] = i/block + 1;         scanf("%d",&k);         memset(cnt,0,sizeof(cnt));         for(int i=1;i<=n;i++)             scanf("%d",&a[i]);         scanf("%d",&m);         for(int i=1;i<=m;i++){             int l1,l2,r1,r2;             scanf("%d%d%d%d",&l1,&r1,&l2,&r2);             q[i].l1 = l1 , q[i].r1 = r1 , q[i].l2 = l2 , q[i].r2 = r2;             p[++num].l = l1 , p[num].r = l2⑴ ;             x = l1*40000+(l2⑴);             mm[x] = num;             p[num].id = num;             p[++num].l = r1+1 , p[num].r = r2 ;             x = (r1+1)*40000+r2;             mm[x] = num;             p[num].id = num;             if(l2⑴ >= r1+1){                 p[++num].l = r1+1 , p[num].r = l2⑴ ;                 x = (r1+1)*40000+(l2⑴);                 mm[x] = num;                 p[num].id = num;             }             p[++num].l = l1 , p[num].r = r2 ;             x = l1*40000+r2;             mm[x] = num;             p[num].id = num;         }         sort(p+1,p+1+num,cmp);         solve();         sort(p+1,p+1+num,cmp2);         for(int i=1;i<=m;i++){             int l1,l2,r1,r2;             l1 = q[i].l1 , l2 = q[i].l2 , r1 = q[i].r1 , r2 = q[i].r2 ;             LL ans = 0;             x = l1*40000+r2;             ans += p[mm[x]].ans;             if(l2⑴>=r1+1){                 x = (r1+1)*40000+(l2⑴);                 ans += p[mm[x]].ans;             }             x = (r1+1)*40000+r2;             ans -= p[mm[x]].ans;             x = l1*40000+(l2⑴);             ans -= p[mm[x]].ans;             printf("%lld ",ans);         }     }     return 0; }
------分隔线----------------------------
------分隔线----------------------------

最新技术推荐