线段树应用 查询区间次小值
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#define clc(arr, val) memset(arr, val, sizeof(arr))
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define IN freopen ("in.txt" , "r" , stdin);
#define OUT freopen ("out.txt" , "w" , stdout);
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int MAXN = 60127;
const int MAXM = 311231;
const int N = 60127;
const int M = 200000;
const int INF = 0x3f3f3f3f;
const LL mod = (LL)1<<32;
#define lson l,m, rt<<1
#define rson m+1,r,rt<<1|1
int ans[MAXN<<2],kao[MAXN<<2][2];
int lll,rrr;
struct node
{
int x,y;
};
int push(int rt)
{
ans[rt]=ans[rt<<1]+ans[rt<<1|1]; //某一年被更新过几次累加到上一个节点
//这个过程看题目需求
int a[4];
a[0]=kao[rt<<1][0];
a[1]=kao[rt<<1][1];
a[2]=kao[rt<<1|1][0]; //rt是最小,那么rt<<1|1必然是次小
a[3]=kao[rt<<1|1][1];
sort(a,a+4);
kao[rt][0]=a[0]; //返回年数最小值
kao[rt][1]=a[1]; //返回年数次小值
}
node gao(node xx,node yy) //每次不断的找最小值和次小值,赋给res,并且xx.y为次小值。
{
int a[4];
a[0]=xx.x;
a[1]=xx.y;
a[2]=yy.x;
a[3]=yy.y;
sort(a,a+4); //有点繁琐
xx.x=a[0];//
xx.y=a[1];
return xx;
}
int update(int R,int a,int l,int r,int rt)//更新l到r的区间,也是就是rrr到l
{
if(l==r)
{
ans[rt]++; //更新的时候,rrr到l的区间内下标加1.
if(kao[rt][0]>=lll)
{
swap(kao[rt][0],kao[rt][1]);
kao[rt][0]=lll; //这边是查找所能返回的最小的年数。
}
else if(kao[rt][1]>lll)
kao[rt][1]=lll; //这边是查找所能返回的最小的年数。
return 0;
}
int m=(l+r)>>1;
if(R<=m)
update(R,a,lson);
else
update(R,a,rson);
push(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return ans[rt]; //返回某一年被更新过几次。
int m=(l+r)>>1;
int res=0;
if(L<=m)
res=res+query(L,R,lson);
if(R>m)
res=res+query(L,R,rson);
return res;
}
node query1(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
node c;
c.x=kao[rt][0];
c.y=kao[rt][1];
return c; //找到返回年数的最小值和次小值赋给res。然后返回不断更新赋值
}
int m=(l+r)>>1;
node res,ree;
res.x=INF,res.y=INF;
ree.x=INF,ree.y=INF;
if(L<=m)
res=query1(L,R,lson);
if(R>m)
ree=query1(L,R,rson);
res=gao(res,ree); //再次赋值。
return res;
}
int build(int l,int r,int rt)
{
kao[rt][0]=kao[rt][1]=INF; //一维二维初始为无穷大 因为要赋值
ans[rt]=0; //所有节点初始为0
if(l==r)
{
return 0; //线段树的所有值初始为0 两句废话
}
int m=(l+r)>>1;
build(lson);
build(rson); //建树
return 0;
}
int main()
{
int n,m,q;
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
build(1,n,1);
for(int i=0; i<m; i++)
{
scanf("%d%d",&rrr,&lll);
update(rrr,1,1,n,1); //更新rrr到1的区间
}
while(q--)
{
int x;
scanf("%d",&x);
int c=query(x,n,1,n,1); //查询x到n的区间
if(c<2)
printf("0\n");
else
{
node aa=query1(x,n,1,n,1); //将次小值的结果赋给aa,并且aa.y为次小值
int ccc=max(x-aa.y,0);
printf("%d\n",ccc);
}
}
}
return 0;
}