题目
https://cn.vjudge.net/problem/HDU-6521
题意
给你n个人 m个聚会 告诉你每个聚会有哪些人参加 问这些人能组成多少对不同的新朋友 之前组成过朋友不再计算
思路
吉司机线段树 记录当前区间已经和哪些组过,查询时如果组过的大于查询的就不再查询 不然就遍历每个没组过的点,统计个数
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 500010;
int n,m,k;
struct node
{
int ma,v; //ma为这个点已经和ma到这个点组过
}a[maxn<<2];
void build(int i,int l,int r)
{
if(l == r)
{
a[i].ma = a[i].v = l;
return ;
}
int mid = (l+r)>>1;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
a[i].ma = max(a[i*2].ma,a[i*2+1].ma);
}
ll updata(int i,int l,int r,int ql,int qr,int x)
{
ll res = 0;
if(x >= a[i].ma) return res;
if(l == r)
{
res += a[i].v - x;
a[i].ma = a[i].v = x;
return res;
}
int mid = (l+r)>>1;
if(ql <= l&&r <= qr)
{
res += updata(i*2,l,mid,ql,mid,x);
res += updata(i*2+1,mid+1,r,mid+1,qr,x);
a[i].ma = max(a[i*2].ma,a[i*2+1].ma);
return res;
}
if(ql <= mid) res += updata(i*2,l,mid,ql,min(qr,mid),x);
if(qr > mid) res += updata(i*2+1,mid+1,r,max(ql,mid),qr,x);
a[i].ma = max(a[i*2].ma,a[i*2+1].ma);
return res;
}
int main()
{
while(scanf("%d%d",&n,&m) != EOF)
{
build(1,1,n);
for(int i = 1;i <= n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ll ans = updata(1,1,n,x,y,x);
printf("%lld\n",ans);
}
}
return 0;
}
//2w8 + 1w7