Description

Input

Output

Sample Input

3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3

Sample Output

2 2
1 1
3 2
2 1

HINT

N=100000,M=1000000

 
对权值建立线段树,对应询问在权值区间内打上标记,那么最后对线段树上的每个节点,问题就转化成HH的项链了。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=<<;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=,f=;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-;
for(;isdigit(c);c=Getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
const int maxm=;
const int maxnode=;
int n,m,first[maxn],next[maxn],to[maxn],cnt;
void AddVal(int u,int v) {
next[++cnt]=first[u];to[cnt]=v;first[u]=cnt;
}
int L[maxm],R[maxm],ans[maxm],ans2[maxm],first2[maxn*],next2[maxnode],to2[maxnode],ToT;
void AddQuery(int u,int v) {
next2[++ToT]=first2[u];to2[ToT]=v;first2[u]=ToT;
}
void query(int o,int l,int r,int ql,int qr,int val) {
if(ql<=l&&r<=qr) AddQuery(o,val);
else {
int mid=l+r>>,lc=o<<,rc=lc|;
if(ql<=mid) query(lc,l,mid,ql,qr,val);
if(qr>mid) query(rc,mid+,r,ql,qr,val);
}
}
struct Solver {
int x,v,t;
bool operator < (const Solver& ths) const {
return x<ths.x;
}
}A[maxn],B[maxm];
int sumv[maxn],clo[maxn],nxt[maxn],clo2[maxn],lst[maxn],T,T2;
void add(int x,int v) {
if(x>n) return;
for(;x<=n;x+=x&-x) {
if(clo[x]==T) sumv[x]+=v;
else clo[x]=T,sumv[x]=v;
}
}
int sum(int x) {
int res=;
for(;x;x-=x&-x) if(clo[x]==T) res+=sumv[x];
return res;
}
void solve(int o,int l,int r) {
if(l!=r) {
int mid=l+r>>,lc=o<<,rc=lc|;
solve(lc,l,mid);solve(rc,mid+,r);
}
int m1=,m2=;
rep(x,l,r) ren A[++m1]=(Solver){to[i],x,};
if(!m1||!first2[o]) return;
T++;
rep(i,,m1) add(A[i].x,);
for(int i=first2[o];i;i=next2[i]) ans[to2[i]]+=sum(R[to2[i]])-sum(L[to2[i]]-);
T++;T2++;
for(int i=first2[o];i;i=next2[i]) B[++m2]=(Solver){L[to2[i]],R[to2[i]],to2[i]};
sort(A+,A+m1+);sort(B+,B+m2+);
dwn(i,m1,) {
if(clo2[A[i].v]!=T2) clo2[A[i].v]=T2,lst[A[i].v]=i,nxt[i]=m1+;
else nxt[i]=lst[A[i].v],lst[A[i].v]=i;
}T2++;
rep(i,,m1) if(clo2[A[i].v]!=T2) {
clo2[A[i].v]=T2;
add(A[i].x,);
}
int j=;
rep(i,,m2) {
while(j<=m1&&A[j].x<B[i].x) {
add(A[j].x,-);
if(nxt[j]<=m1) add(A[nxt[j]].x,);
j++;
}
ans2[B[i].t]+=sum(B[i].v)-sum(B[i].x-);
}
}
int main() {
n=read();m=read();
rep(i,,n) AddVal(read(),i);
rep(i,,m) {
L[i]=read();R[i]=read();
int a=read(),b=read();
query(,,n,a,b,i);
}
solve(,,n);
rep(i,,m) printf("%d %d\n",ans[i],ans2[i]);
return ;
}

莫队大法也很资瓷啊。对权值分块以牺牲询问复杂度的代价来降低修改复杂度。

不知道为什么O(Msqrt(N))的做法比O(Mlog^2N)的做法快了3倍。。。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=<<;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=,f=;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-;
for(;isdigit(c);c=Getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
const int maxm=;
int n,m,A[maxn],blo[maxn],st[maxn],en[maxn];
struct Query {
int l,r,a,b,id;
bool operator < (const Query& ths) const {
if(blo[l]==blo[ths.l]) return r<ths.r;
return l<ths.l;
}
}Q[maxm];
int ans[maxm],ans2[maxm],cnt[maxn],sum[maxn],bloans[maxn];
void add(int x) {
if(!cnt[x]) bloans[blo[x]]++;
cnt[x]++;sum[blo[x]]++;
}
void del(int x) {
cnt[x]--;sum[blo[x]]--;
if(!cnt[x]) bloans[blo[x]]--;
}
void query(int x,int l,int r) {
rep(i,blo[l]+,blo[r]-) ans2[x]+=bloans[i],ans[x]+=sum[i];
if(blo[l]==blo[r]) rep(i,l,r) ans2[x]+=(cnt[i]>),ans[x]+=cnt[i];
else {
rep(i,l,en[blo[l]]) ans2[x]+=(cnt[i]>),ans[x]+=cnt[i];
rep(i,st[blo[r]],r) ans2[x]+=(cnt[i]>),ans[x]+=cnt[i];
}
}
int main() {
n=read();m=read();int SIZE=(int)sqrt(n);
rep(i,,n) {
A[i]=read();blo[i]=(i-)/SIZE+;
if(!st[blo[i]]) st[blo[i]]=i;
en[blo[i]]=i;
}
rep(i,,m) Q[i].l=read(),Q[i].r=read(),Q[i].a=read(),Q[i].b=read(),Q[i].id=i;
sort(Q+,Q+m+);
int l=,r=;
rep(i,,m) {
while(l>Q[i].l) add(A[--l]);
while(r<Q[i].r) add(A[++r]);
while(l<Q[i].l) del(A[l++]);
while(r>Q[i].r) del(A[r--]);
query(Q[i].id,Q[i].a,Q[i].b);
}
rep(i,,m) printf("%d %d\n",ans[i],ans2[i]);
return ;
}

BZOJ3236: [Ahoi2013]作业的更多相关文章

  1. [bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业

    [bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业 bzoj   bzoj 题目大意:一个序列,m个询问在$[l,r]$区间的$[x,y]$范围内的数的个数/种类. ...

  2. BZOJ3236 [Ahoi2013]作业 【莫队 + 树状数组】

    题目链接 BZOJ3236 题解 没想到这题真的是如此暴力 #include<algorithm> #include<iostream> #include<cstring ...

  3. [BZOJ3236]:[Ahoi2013]作业(莫队+分块)

    题目传送门 题目描述 此时已是凌晨两点,刚刚做了$Codeforces$的小$A$掏出了英语试卷.英语作业其实不算多,一个小时刚好可以做完.然后是一个小时可与做完的数学作业,接下来是分别都是一个小时可 ...

  4. BZOJ3236[Ahoi2013]作业——莫队+树状数组/莫队+分块

    题目描述 输入 输出 样例输入 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 样例输出 2 2 1 1 3 2 2 1 提示 N=100000,M=1000000 ...

  5. BZOJ3236:[AHOI2013]作业(莫队,分块)

    Description Input Output Sample Input 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 Sample Output 2 2 1 ...

  6. BZOJ3236: [Ahoi2013]作业 树状数组维护 莫队

    水果~~~~ 关于四个while可行性的证明:区间有正确性所以不管那团小东西用没有duang~反它最终总会由于两次覆盖二准确 关于区间种数可行性的证明:他会在0 1间(或两边)来回跳动(过程中),最终 ...

  7. 【莫队算法】【权值分块】bzoj3236 [Ahoi2013]作业

    莫队显然.然后维护转移的时候如果用树状数组,则很容易TLE.所以用权值分块维护转移. 总复杂度O(m*sqrt(n)). #include<cstdio> #include<algo ...

  8. [BZOJ3236][AHOI2013]作业:树套树/莫队+分块

    分析 第一问随便搞,直接说第二问. 令原数列为\(seq\),\(pre_i\)为\(seq_i\)这个值上一个出现的位置,于是可以简化询问条件为: \(l \leq i \leq r\) \(a \ ...

  9. bzoj3809 Gty的二逼妹子序列 & bzoj3236 [Ahoi2013]作业 莫队+分块

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3809 https://lydsy.com/JudgeOnline/problem.php?id ...

随机推荐

  1. linux之eval用法(高级bash程序员的必修之技)

    1. eval command-line 其中command-line是在终端上键入的一条普通命令行.然而当在它前面放上eval时,其结果是shell在执行命令行之前扫描它两次.如: pipe=&qu ...

  2. QEMU 使用的镜像文件:qcow2 与 raw

    qcow2 的基本原理 qcow2 镜像格式是 QEMU 模拟器支持的一种磁盘镜像.它也是可以用一个文件的形式来表示一块固定大小的块设备磁盘.与普通的 raw 格式的镜像相比,有以下特性: 更小的空间 ...

  3. hdu5832 A water problem

    A water problem Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  4. DisJSet:Find them, Catch them(POJ 1703)

    抓住他们! 题目大意:两个黑社会帮派,互相打架,现在你很多条信息,要你确定两个人是否属于不同帮派 这题很有趣,题目不是直接给你两个人是否是一个帮派的,他给你的是不同帮派的,也就是给你很多个不同的要你找 ...

  5. 【python】继承时注意事项

    1. __init__ 注意事项 如果父类有__init__函数,子类没有,则子类自动调用父类__init__函数 如果父类有__init__函数,子类也有,则子类必须主动调用父类__init__函数 ...

  6. HDU 5317 RGCDQ (数论素筛)

    RGCDQ Time Limit: 3000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status ...

  7. VS 高亮显示不带后缀的C++头文件

    工具-选项-文本编辑器-文件扩展名-勾选“将无扩展名文件映射到(M)” Microsoft Visual C++

  8. ajax 中文乱码问题 主要是IE浏览器

    解决方案: 提交前采用encodeURI两次编码,注:一定是两次 举例: var taText = $("#txtName").val(); taText = encodeURI( ...

  9. Unity3D入门之GUI基础以及常用GUI控件使用(2)

    1.GUI基础 (1)GUI部分是每帧擦除重绘的,只应该在OnGUI中绘制GUI,按钮:GUILayout.Button(“Hello”); 只读标签:GUILayout.Label() (2)修改控 ...

  10. AppPoolService-IIS应用程序池辅助类(C#控制应用程序池操作)

    using System.Collections.Generic; using System.DirectoryServices; using System.Linq; using Microsoft ...