Hdu 5213-Lucky 莫队,容斥原理,分块
2024-10-12 07:57:10
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5213
Lucky
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 763 Accepted Submission(s): 249
Problem Description
WLD is always very lucky.His secret is a lucky number K.k is a fixed odd number. Now he meets a stranger with N numbers:a1,a2,...,aN.The stranger asks him Mquestions.Each question is like this:Given two ranges [Li,Ri] and [Ui,Vi],you can choose two numbers X and Y to make aX+aY=K.The X you can choose is between Li and Ri and the Y you can choose is between Ui and Vi.How many pairs of numbers(X,Y) you can choose?
If WLD can answer all the questions correctly,he'll be the luckiest man in the world.Can you help him?
If WLD can answer all the questions correctly,he'll be the luckiest man in the world.Can you help him?
Input
There are multiple cases.(At MOST 5)
For each case:
The first line contains an integer N(1≤N≤30000).
The following line contains an integer K(2≤K≤2∗N),WLD's lucky number.K is odd.
The following line contains N integers a1,a2,...,aN(1≤ai≤N).
The following line contains an integer M(1≤M≤30000),the sum of the questions WLD has to answer.
The following M lines,the i-th line contains 4 numbers Li,Ri,Ui,Vi(1≤Li≤Ri<Ui≤Vi≤N),describing the i-th question the stranger asks.
Output
For each case:
Print the total of pairs WLD can choose for each question.
Sample Input
5
3
1 2 1 2 3
1
1 2 3 5
3
1 2 1 2 3
1
1 2 3 5
Sample Output
2
Hint
a1+a4=a2+a3=3=K.
So we have two pairs of numbers (1,4) and (2,3).
Good luck!
Source
Recommend
题意:给你一个a数列,再给出一些询问,每次询问给两个区间,分别为[l,r]和[u,v],且1<=l<=r<u<=v<=n,让你从[l,r]中找一个a[i],在[u,v]中找一个a[j],使得a[i]+a[j]=K,问有多少对。
题解:
好几天没发题解了。。。
来个莫队压压惊。。。
莫队+容斥
莫队很好想的,主要是如何用容斥。
我们把每组询问的两个区间写出来。
l-----r--------u-----v
|<A>|
|<B>|
|<--C-->|
然后定义f(x,y)为第一个数i在x区间,第二个数j在y区间的a[i]+a[j]=K的方案数。
我们要求的为f(A,B)=f(A+B+C,A+B+C)-f(A+C,A+C)-f(B+C,B+C)+f(C,C)
然后就可以用莫队做了。
这里有些小技巧:在加区间的时候,我们可以把区间的 两端点 和 当前区间的值是加还是减 记录下来,这样比较简单。
另外这道题的数组大小好离奇。。。
具体看程序:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 30010
#define MAXM 30010
struct node
{
int l,r,id,fh;
}q[MAXM*];
int a[MAXN],pos[MAXN],sum[MAXN*],N,ans[MAXM*];
int read()
{
int s=,fh=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
return s*fh;
}
void Add(int ll,int rr,int ii,int ff){q[++N].l=ll;q[N].r=rr;q[N].id=ii;q[N].fh=ff;}
bool cmp(node aa,node bb)
{
if(pos[aa.l]==pos[bb.l])return aa.r<bb.r;
return aa.l<bb.l;
}
int main()
{
int n,k,i,m,block,tot,L,R,U,V;
while(scanf("%d",&n)!=EOF)
{
k=read();
for(i=;i<=n;i++)a[i]=read();
m=read();
N=;
for(i=;i<=m;i++)
{
L=read();R=read();U=read();V=read();
Add(L,V,i,);Add(L,U-,i,-);Add(R+,V,i,-);Add(R+,U-,i,);
}
block=(int)sqrt(n);
for(i=;i<=n;i++)pos[i]=(int)(i-)/block+;
sort(q+,q+N+,cmp);
memset(ans,,sizeof(ans));
L=;R=;
tot=;//当前区间有多少对a[i]+a[j]=k.
memset(sum,,sizeof(sum));//当前区间数字为i的有sum[i]个.
for(i=;i<=N;i++)
{
while(L<q[i].l)
{
sum[a[L]]--;
tot-=sum[k-a[L]];
//sum[a[L]]--;
//if(k==a[L]*2)tot++;
L++;
}
while(L>q[i].l)
{
L--;
tot+=sum[k-a[L]];
sum[a[L]]++;
}
while(R<q[i].r)
{
R++;
tot+=sum[k-a[R]];
sum[a[R]]++;
}
while(R>q[i].r)
{
sum[a[R]]--;
tot-=sum[k-a[R]];
//sum[a[R]]--;
//if(k==a[R]*2)tot++;
R--;
}
ans[q[i].id]+=q[i].fh*tot;
}
for(i=;i<=m;i++)printf("%d\n",ans[i]);
}
fclose(stdin);
fclose(stdout);
return ;
}
最新文章
- Lambda 表达式递归用法实例
- RMAN-06023: no backup or copy of datafile 1 found to restore
- iOS中UIImageView的填充模式
- ComboBox的数据联动
- UVA232字符串处理
- iOS开发中使用CocoaPods来管理第三方的依赖程序
- stage划分
- linux http请求监控工具httpry---官方文档
- Linux_Shell符号及各种解释对照表
- orcl 行转列的存储过程
- [转]tomcat启动报错too low setting for -Xss
- Ubuntu Desktop: 备份与还原
- php实现多进程
- ElasticSearch 2 (5) - Document APIs
- 等待进程结束wait,waitpid
- js的正则匹配 和 blur
- c# 调用微信小程序
- 【BZOJ1562】【NOI2009】变换序列(二分图匹配)
- Hibernate4.3.5搭建Log4j日志环境
- 前端MVC