偏序专题
https://www.luogu.com.cn/problem/P2163
很容易想到二维前缀和 但是因为数据范围是不允许的 就和之前校赛的题目一模一样
做这个题目前先看一下这个题目
只要将查询的点分为四个点 放入扫描数组中 再从小到大扫描一遍即可
#include<bits/stdc++.h>
#define reg register
using namespace std;
int n;
int c[2500005];
struct star{
int x,y;
int pos;//pos用来方便统计答案与判定是否为虚点
};
star st[2500005];
int ans[500005][5];
int tot[500005];
int x1_[500005],x2_[500005],y1_[500005],y2_[500005];//不要轻易用x1,x2,y1,y2...
int b[2500005],p;
bool cmp(star x,star y)
{
if(x.x!=y.x)return x.x<y.x;
if(x.y!=y.y)return x.y<y.y;
return x.pos<y.pos;
}
inline void add(int x,int y)
{
for(reg int i=x;i<=n;i+=i&-i)c[i]+=y;
}
inline int ask(int x)
{
int ans=0;
for(reg int i=x;i>=1;i-=i&-i)ans+=c[i];
return ans;
}
inline int lsh(int x)
{
return lower_bound(b+1,b+p+1,x)-b;
}
int main()
{
//printf("%d",sizeof(ans)/1024/1024);
int m;
scanf("%d%d",&n,&m);
if(n==0){
for(reg int i=1;i<=m;i++)printf("0\n");
return 0;
}
if(m==0)
{
return 0;
}
for(reg int i=1;i<=n;i++)scanf("%d%d",&st[i].x,&st[i].y),st[i].pos=0;
for(reg int i=1;i<=m;i++){
scanf("%d%d%d%d",&x1_[i],&y1_[i],&x2_[i],&y2_[i]),st[++n].x=x1_[i]-1,st[n].y=y1_[i]-1,st[n].pos=i;
st[++n].x=x2_[i],st[n].y=y2_[i],st[n].pos=i;
st[++n].x=x2_[i],st[n].y=y1_[i]-1,st[n].pos=i;
st[++n].y=y2_[i],st[n].x=x1_[i]-1,st[n].pos=i;
}
sort(st+1,st+n+1,cmp);
for(reg int i=1;i<=n;i++)b[i]=st[i].y;
sort(b+1,b+n+1);
p=unique(b+1,b+n+1)-(b+1);
for(reg int i=1;i<=n;i++)
{
if(st[i].pos)ans[st[i].pos][++tot[st[i].pos]]=ask(lsh(st[i].y));
//printf("%d\n",ask(lsh(st[i].y)));
else if(st[i].pos==0)add(lsh(st[i].y),1);
//printf("st[i].y=%d,ask(st[i].y)=%d\n",lsh(st[i].y),ask(st[i].y));
}
for(reg int i=1;i<=m;i++)
printf("%d\n",ans[i][4]-ans[i][3]-ans[i][2]+ans[i][1]);
return 0;
}
https://codeforces.com/problemset/problem/1320/C
和上题目思路大致相同 先将一维顺序化 因为维护最大值和区间修改 所以第二维用线段树维护
只需要在当前 [y+1,maxn] 这个区间上加上这个点的贡献就可以了
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <cstdio>
#include <iomanip>
#include <time.h>
#include <bitset>
#include <cmath>
#include <sstream>
#include <iostream>
#define LL long long
#define ls nod<<1
#define rs (nod<<1)+1
#define pii pair<int,int>
#define mp make_pair
const double eps = 1e-10;
const int maxn = 1e6 + 1;
const LL mod = 1e9 + 7;
const LL INF = 1e18;
int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
using namespace std;
struct segment_tree {
LL val;
int lazy;
}tree[maxn << 2];
LL a[maxn],b[maxn];
vector<pii> vec[maxn];
void build (int l,int r,int nod) {
if (l == r) {
tree[nod].val = -b[l];
return ;
}
int mid = (l + r ) >> 1;
build(l,mid,ls);
build(mid+1,r,rs);
tree[nod].val = max(tree[ls].val,tree[rs].val);
}
void pushdown(int nod) {
tree[ls].lazy += tree[nod].lazy;
tree[rs].lazy += tree[nod].lazy;
tree[ls].val += tree[nod].lazy;
tree[rs].val += tree[nod].lazy;
tree[nod].lazy = 0;
}
void modify(int l,int r,int ql,int qr,int k,int nod) {
if (ql <= l && qr >= r) {
tree[nod].lazy += k;
tree[nod].val += k;
return ;
}
if (tree[nod].lazy)
pushdown(nod);
int mid = (l + r) >> 1;
if (ql <= mid)
modify(l,mid,ql,qr,k,ls);
if (qr > mid)
modify(mid+1,r,ql,qr,k,rs);
tree[nod].val = max(tree[ls].val,tree[rs].val);
}
LL query(int l,int r,int ql,int qr,int nod) {
if (ql <= l && qr >= r)
return tree[nod].val;
if (tree[nod].lazy)
pushdown(nod);
int mid = (l + r ) >> 1;
LL ans = 0;
if (ql <= mid)
ans += query(l,mid,ql,qr,ls);
if (qr > mid)
ans += query(mid+1,r,ql,qr,rs);
return ans;
}
int main() {
for (int i = 0;i <= maxn;i++)
a[i] = b[i] = INF;
int n,m,p;
cin >> n >> m >> p;
for (int i = 1;i <= n;i++) {
int x;
LL y;
cin >> x >> y;
a[x] = min(a[x],y);
}
for (int i = 1;i <= m;i++) {
int x;
LL y;
cin >> x >> y;
b[x] = min(b[x],y);
}
for (int i = 1;i <= p;i++) {
int x,y,z;
cin >> x >> y >> z;
vec[x].push_back(mp(y,z));
}
build(1,maxn,1);
LL ans = -INF;
for (int i = 1;i <= maxn;i++) {
ans = max(ans,tree[1].val-a[i]);
for (pii o : vec[i]) {
if (o.first+1 < maxn)
modify(1,maxn,o.first+1,maxn,o.second,1);
}
}
cout << ans << endl;
return 0;
}