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. 《ASP.NET1200例》C# WINFORM程序的三层架构如何建立的。

    先添加-新建项目-windows应用程序,然后在右边的解决方案资源管理器上面,在当前的解决方案上面右击,点,添加-新建项目-类库,分别建立.DAL,BLL,Model三个项目,然后,在DAL项目上右击 ...

  2. 使用WebDriver遇到的那些坑(转)

    http://www.huangbowen.net/blog/2013/06/25/practice-of-webdriver/ 在做web项目的自动化端到端测试时主要使用的是Selenium Web ...

  3. 13.第一个只出现一次的字符[FindFirstNotRepeatingChar]

    [题目] 在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b. [分析] 这道题是2006年google的一道笔试题. 看到这道题时,最直观的想法是从头开始扫描这个字符串中的 ...

  4. TinyXML 在vs2010 VC++使用

    1.下载TinyXML  http://www.grinninglizard.com/tinyxml/  解压缩,将以下六个文件复制到您的工程项目文件(跟您的cpp文件在一个目录下)中 tinyxml ...

  5. MPlayer-ww 增加边看边剪切功能+生成高质量GIF功能

    http://pan.baidu.com/s/1eQm5a74 下载FFmpeg palettegen paletteuse documentation 需要下载 FFmpeg2.6 以上 并FFmp ...

  6. Greedy:Cleaning Shifts(POJ 2376)

      牛的大扫除 题目大意:农夫有N只牛,这些牛要帮助打扫农舍,这些牛只能打扫固定位置(千万要注意这个位置不是连续的),每一段区间必须至少有一只牛打扫,问你至少需要多少只牛?(如果区间不能完全被覆盖,则 ...

  7. 【python】filter()

    来源:http://www.jb51.net/article/54316.htm filter函数: filter()函数可以对序列做过滤处理,就是说可以使用一个自定的函数过滤一个序列,把序列的每一项 ...

  8. eclipse 反编译插件安装

      1.下载jad.exe和jadclipse_3.3.0.jar 2.将jad.exe拷贝到%JAVA_HOME%bin目录下,将jadclipse_3.3.0.jar拷贝到eclipse的plug ...

  9. exit()与_exit()函数的区别(Linux系统中)

    注:exit()就是退出,传入的参数是程序退出时的状态码,0表示正常退出,其他表示非正常退出,一般都用-1或者1,标准C里有EXIT_SUCCESS和EXIT_FAILURE两个宏,用exit(EXI ...

  10. C#开发微信公众平台-就这么简单(附Demo)(转载)

    转载地址:http://www.cnblogs.com/xishuai/p/3625859.html 写在前面 服务号和订阅号 URL配置 创建菜单 查询.删除菜单 接受消息 发送消息(图文.菜单事件 ...