zoukankan      html  css  js  c++  java
  • 【洛谷5268】[SNOI2017] 一个简单的询问(莫队)

    点此看题面

    • 给定一个长度为(n)的序列。
    • (q)次询问,每次给定两个区间,询问有多少种方式从这两个区间中选出两个相同的数。
    • (n,qle5 imes10^4)

    简单容斥+莫队

    考虑题目要求的是(F(l_1,r_1,l_2,r_2)),那么显然可以对它做一个容斥,把它裂成四个区间,得到:

    [F(1,r_1,1,r_2)-F(1,l_1-1,1,r_2)-F(1,r_1,1,l_2-1)+F(1,l_1-1,1,l_2-1) ]

    然后就是对于莫队不要有太局限的想法,认为它只能处理区间的问题,实际上这种两个指针移动的问题都可以用莫队解决。

    学过莫队的人应该仔细想想就能明白这道题该怎么做吧。

    代码:(O(nsqrt n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 50000
    #define LL long long
    using namespace std;
    int n,m,a[N+5],sz,bl[N+5],c1[N+5],c2[N+5];LL ans[N+5];
    struct Q
    {
    	int op,p,a,b;I Q(CI t=0,CI i=0,CI x=0,CI y=0):op(t),p(i),a(x),b(y){}
    	I bool operator < (Con Q& o) Con {return bl[a]^bl[o.a]?a<o.a:(bl[a]&1?b<o.b:b>o.b);}
    }q[4*N+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
    ');}
    }using namespace FastIO;
    int main()
    {
    	RI i,l1,r1,l2,r2;for(read(n),sz=sqrt(n),i=1;i<=n;++i) read(a[i]),bl[i]=(i-1)/sz+1;
    	for(read(m),i=1;i<=m;++i) read(l1,r1,l2,r2),q[4*i-3]=Q(1,i,r1,r2),
    		q[4*i-2]=Q(-1,i,r1,l2-1),q[4*i-1]=Q(-1,i,l1-1,r2),q[4*i]=Q(1,i,l1-1,l2-1);//容斥,裂成四个区间
    	RI A=0,B=0;LL t=0;for(sort(q+1,q+4*m+1),i=1;i<=4*m;ans[q[i].p]+=q[i].op*t,++i)
    	{
    		W(A<q[i].a) ++c1[a[++A]],t+=c2[a[A]];W(A>q[i].a) --c1[a[A]],t-=c2[a[A--]];//移动A指针
    		W(B<q[i].b) ++c2[a[++B]],t+=c1[a[B]];W(B>q[i].b) --c2[a[B]],t-=c1[a[B--]];//移动B指针
    	}
    	for(i=1;i<=m;++i) writeln(ans[i]);return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Flutter 步骤进度组件
    程序员到底要不要学习框架、库和工具
    Flutter 吐血整理组件继承关系图
    超过百万的StackOverflow Flutter 问题
    Flutter 实现网易云音乐字幕
    Flutter 实现虎牙/斗鱼 弹幕效果
    Flutter AbsorbPointer 与 IgnorePointer的区别
    《Flutter 小技巧》一行禁用App,一行置灰App,致敬
    Python 任务自动化工具:nox 的配置与 API
    Flask 作者 Armin Ronacher:我不觉得有异步压力
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5268.html
Copyright © 2011-2022 走看看