【BZOJ4822】 [Cqoi2017]老C的任务

11 篇文章 0 订阅
3 篇文章 0 订阅

此题本来是一个很好的二维线段树模板题,然而居然卡空间(至少洛谷上是的)。

以下是二维线段树写法(大概70分):

#include <bits/stdc++.h>
#define gc getchar()
#define N 100009
#define M 16000009
#define mp make_pair
#define pb push_back
#define sz(x) (int)x.size()
#define root 1,1,MaxN
#define Root rt[cur],1,MaxM
#define NOW int cur,int l,int r
#define Now int &cur,int l,int r
#define mid (l+r>>1)
#define lc cur<<1
#define rc lc|1
#define lson lc,l,mid
#define rson rc,mid+1,r
#define Lson ls[cur],l,mid
#define Rson rs[cur],mid+1,r
#define ll long long
using namespace std;
ll p[N],sum[M];
int n,m,x[N],y[N],MaxN,MaxM,rt[N<<2],ls[M],rs[M],cnt;
vector<int> X,Y;
int read()
{
    char ch;
    int x=1;
    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
    int s=ch-'0';
    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';
    return s*x;
}
void Ins(Now,int y,ll p)
{
    if (!cur) cur=++cnt;
    sum[cur]+=p;
    if (l==r) return;
    if (y<=mid) Ins(Lson,y,p);
    else Ins(Rson,y,p);
}
void ins(NOW,int x,int y,ll p)
{
    Ins(Root,y,p);
    if (l==r) return;
    if (x<=mid) ins(lson,x,y,p);
    else ins(rson,x,y,p);
}
ll Qry(Now,int L,int R)
{
    if (!cur) return 0;
    if (L<=l&&R>=r) return sum[cur];
    ll ans=0;
    if (L<=mid) ans+=Qry(Lson,L,R);
    if (R>mid) ans+=Qry(Rson,L,R);
    return ans;
}
ll qry(NOW,int l1,int r1,int l2,int r2)
{
    if (l1>r1||l2>r2||r1==0||r2==0||l1==MaxN+1||l2==MaxM+1) return 0ll;
    if (l1<=l&&r1>=r) return Qry(Root,l2,r2);
    ll ans=0;
    if (l1<=mid) ans+=qry(lson,l1,r1,l2,r2);
    if (r1>mid) ans+=qry(rson,l1,r1,l2,r2);
    return ans;
}
int main()
{
    n=read(),m=read();
    for (int i=1;i<=n;i++)
    {
        x[i]=read(),y[i]=read(),p[i]=read();
        X.pb(x[i]),Y.pb(y[i]);
    }
    sort(X.begin(),X.end());
    sort(Y.begin(),Y.end());
    X.erase(unique(X.begin(),X.end()),X.end());
    Y.erase(unique(Y.begin(),Y.end()),Y.end());
    MaxN=sz(X),MaxM=sz(Y);
    for (int i=1;i<=n;i++)
    {
        x[i]=lower_bound(X.begin(),X.end(),x[i])-X.begin()+1;
        y[i]=lower_bound(Y.begin(),Y.end(),y[i])-Y.begin()+1;
        ins(root,x[i],y[i],p[i]);
    }
    for (int i=1;i<=m;i++)
    {
        int x1=read(),y1=read(),x2=read(),y2=read();
        x1=lower_bound(X.begin(),X.end(),x1)-X.begin()+1;
        y1=lower_bound(Y.begin(),Y.end(),y1)-Y.begin()+1;
        x2=upper_bound(X.begin(),X.end(),x2)-X.begin();
        y2=upper_bound(Y.begin(),Y.end(),y2)-Y.begin();
        printf("%lld\n",qry(root,x1,x2,y1,y2));
    }
    return 0;
}
然后另外一种显然就是离线拆询问+扫描线+树状数组啦:

#include <bits/stdc++.h>
#define gc getchar()
#define N 100009
#define M 16000009
#define mp make_pair
#define pb push_back
#define sz(x) (int)x.size()
#define root 1,1,MaxN
#define Root rt[cur],1,MaxM
#define NOW int cur,int l,int r
#define Now int &cur,int l,int r
#define mid (l+r>>1)
#define lc cur<<1
#define rc lc|1
#define lson lc,l,mid
#define rson rc,mid+1,r
#define Lson ls[cur],l,mid
#define Rson rs[cur],mid+1,r
#define ll long long
using namespace std;
ll p[N],sum[M],ans[N];
int n,m,x[N],y[N],MaxN,MaxM,cnt;
vector<int> X,Y;
struct coordinate
{
	int x,y;
	ll p;
	coordinate(int x=0,int y=0,ll p=0):x(x),y(y),p(p){}
}point[N];
bool operator <(const coordinate &a,const coordinate &b)
{
	return a.x<b.x;
}
struct node
{
	int x,l,r,pos;
	node(int x=0,int l=0,int r=0,int pos=0):x(x),l(l),r(r),pos(pos){}
}q[N<<1];
bool operator <(const node &a,const node &b)
{
	return a.x<b.x;
}
int read()
{
    char ch;
    int x=1;
    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
    int s=ch-'0';
    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';
    return s*x;
}
int lowbit(int x)
{
	return x&(-x);
}
void add(int x,ll y)
{
	for (;x<=n;x+=lowbit(x)) sum[x]+=y;
}
ll qry(int x)
{
	ll ans=0;
	for (;x;x-=lowbit(x)) ans+=sum[x];
	return ans;
}
int main()
{
    n=read(),m=read();
    for (int i=1;i<=n;i++)
    {
        x[i]=read(),y[i]=read(),p[i]=read();
        X.pb(x[i]),Y.pb(y[i]);
    }
    sort(X.begin(),X.end());
    sort(Y.begin(),Y.end());
    X.erase(unique(X.begin(),X.end()),X.end());
    Y.erase(unique(Y.begin(),Y.end()),Y.end());
    MaxN=sz(X),MaxM=sz(Y);
    for (int i=1;i<=n;i++)
    {
        x[i]=lower_bound(X.begin(),X.end(),x[i])-X.begin()+1;
        y[i]=lower_bound(Y.begin(),Y.end(),y[i])-Y.begin()+1;
        point[i]=coordinate(x[i],y[i],p[i]);
    }
    sort(point+1,point+n+1);
    for (int i=1;i<=m;i++)
    {
        int x1=read(),y1=read(),x2=read(),y2=read();
        x1=lower_bound(X.begin(),X.end(),x1)-X.begin()+1;
        y1=lower_bound(Y.begin(),Y.end(),y1)-Y.begin()+1;
        x2=upper_bound(X.begin(),X.end(),x2)-X.begin();
        y2=upper_bound(Y.begin(),Y.end(),y2)-Y.begin();
        q[++cnt]=node(x1-1,y1,y2,i);
        q[++cnt]=node(x2,y1,y2,i);
    }
    sort(q+1,q+cnt+1);
    int now=1;
    for (int i=1;i<=cnt;i++)
    {
    	while (point[now].x<=q[i].x&&now<=n) add(point[now].y,point[now].p),now++;
    	if (!ans[q[i].pos]) ans[q[i].pos]=qry(q[i].r)-qry(q[i].l-1);
    	else ans[q[i].pos]=qry(q[i].r)-qry(q[i].l-1)-ans[q[i].pos];
	}
	for (int i=1;i<=m;i++)
		printf("%lld\n",ans[i]);
    return 0;
}

(就不能开512MB的空间吗???)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值