Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 235 Accepted Submission(s): 87
Problem Description
n person have just entered a company, and Xiaoxun, as a supervisor, gives each of them a number from 1 to n that is not repeated.
In order to let them to get to know each other better, they would have a party every day, and there was a limit on the number of people at each party. Xiaoxun didn't want to find a way to find people randomly. So every time he had a party, he would only invite people with numbers in a certain interval to play.
The people who come to the party will get to know each other, and Xiaoxun wants to know how effective each party is. The effect is evaluated as the number of pairs of people at this party who did not appear at the same previous party.
Input
There are mutiple test cases.
Each case starts with a line containing two integers n,m(n≤5×105,m≤5×105)which represent the number of people and the number of parties. And this is followed by m lines each containing two integers l,r(1≤l≤r≤n) which mean the interval, and only the people whose number in the interval can take part in this party.
Output
For each case you should print m lines.
Each line containing a integer mean the effect of this party.
Sample Input
5 4 1 2 4 5 1 4 2 5
Sample Output
1 1 5 2
Hint
explaination of sample: The first party: 1-2 The second party: 4-5 The third party: 1-3 1-4 2-3 2-4 3-4 The fourth party: 2-5 3-5
Source
2019中山大学程序设计竞赛(重现赛)
Recommend
liuyiding | We have carefully selected several similar problems for you: 6521 6520 6519 6518 6517
题意:
有n个人,开m次派对,每次派对每对人会相互认识对方。对于每一次派对,我们要求出新认识的pair的数量。
分析:
思路参考:学长博客:https://blog.csdn.net/LSD20164388/article/details/89413657
这题关键的一个性质就是认识的人是一段连续的区间。因为是算数量,所以可以把相互认识当作有向边,每个边当作从小连向大的有向边即可,即下面初始a[i]=i,最大也只能是i。
我们设a[i]=k,表示(k,i),(k+1,i),.....(i-1,i)已经被计算过答案,不需要添加。
假设我们查询的区间为(l,r),
如果l>=max(a[l].......a[r]),不能算作答案了。
如果l
综上,该线段树查询功能为:如果该区间的某一个值大于或小于最大值,需要暴力的修改这个位置的值,需要该线段树。
#include
using namespace std;
const int N=500010;
#define ll long long
int n,m;
struct node //线段树
{
int l,r;
ll dat,ma;
}tree[N*4];
void PushUp(int x) //线段树维护结点信息
{
tree[x].ma=max(tree[x<<1].ma,tree[x<<1|1].ma);
}
void build(int x,int l,int r) //线段树建树
{
tree[x].l=l;
tree[x].r=r;
if (l==r) //叶子节点
{
tree[x].ma=tree[x].dat=l;
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
PushUp(x);
}
ll query(int x,int l,int r,int val) //线段树区间查询
{
if(val>=tree[x].ma) return 0;
ll ans=0;
if(tree[x].l==tree[x].r)
{
ans+=tree[x].dat-val;
tree[x].ma=tree[x].dat=val;
return ans;
}
int mid=(tree[x].l+tree[x].r)>>1;
if (l<=tree[x].l&&r>=tree[x].r)
{
ans+=query(x<<1,l,mid,val);
ans+=query(x<<1|1,mid+1,r,val);
PushUp(x);
return ans;
}
if (l<=mid) ans+=query(x<<1,l,min(r,mid),val);
if (r>mid) ans+=query(x<<1|1,max(l,mid+1),r,val);
PushUp(x);
return ans;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
build(1,1,n);
for(int i=1;i<=m;++i){
int l,r;
scanf("%d%d",&l,&r);
ll ans=query(1,l,r,l);
printf("%lld\n",ans);
}
}
return 0;
}