首页 > 其他分享 >P5268 [SNOI2017] 一个简单的询问

P5268 [SNOI2017] 一个简单的询问

时间:2023-09-24 21:22:36浏览次数:40  
标签:int 询问 tot ++ SNOI2017 include sum P5268 fo

一个简单的询问

显然这个询问并不简单
如果做过莫比乌斯反演入门题problem b就会想到利用容斥将询问拆成四个

那么我们现在的问题变成如何求
[1,l]
[1,r]
两个区间之间的答案,那么也是直接用莫队即可,只是维护的是两个区间的右端点,和原来的莫队有一些不一样,但是大体相同。

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
#define mk(x,y) make_pair((x),(y))
#define A puts("YES")
#define B puts("NO")
using namespace std;
typedef long long ll;
const ll inf=1ll<<60;
const int N=5e4+5;
int S;
struct node{
	int l,r,id,op;
	bool operator < (const node&x) const {
		if (l/S != x.l/S) return l<x.l;
		return (l/S)&1 ? r<x.r : r>x.r;
	}
};
node q[N*8];
int c[N],n,m,tot,l,r;
ll a[N],b[N],sum,ans[N];
void add1(int x){
	sum+=b[x];
	a[x]++;
}
void add2(int x){
	sum+=a[x];
	b[x]++;
}
void sub1(int x){
	sum-=b[x];
	a[x]--;
}
void sub2(int x){
	sum-=a[x];
	b[x]--;
}
int main(){
	
//	freopen("data.in","r",stdin);    
	scanf("%d",&n);
	fo(i,1,n) scanf("%d",&c[i]);
	
	S=(int)pow(n,0.5);
	scanf("%d",&m);
	fo(p,1,m) {
		int x,y,z,w;
		scanf("%d %d %d %d",&x,&y, &z,&w);
		
		q[++tot]=(node){y,w,p,1};
		if ((x-1)>0) q[++tot]=(node){x-1,w,p,-1};
		if ((z-1)>0) q[++tot]=(node){y,z-1,p,-1};
		if ((x-1)>0 && (z-1)>0)	q[++tot]=(node){x-1,z-1,p,1};
	}
	fo(i,1,tot) if (q[i].l>q[i].r) swap(q[i].l, q[i].r);
	
	sort(q+1,q+tot+1);
	
//	fo(i,1,tot) {
//		printf("%d %d %d %d\n",q[i].l,q[i].r, q[i].id, q[i].op);
//	}

	
	l=0; r=0;
	while (l<q[1].l) ++a[c[++l]];
	while (r<q[1].r) {
		sum+=a[c[++r]];
		b[c[r]]++;
	}
	
	ans[q[1].id]+=(ll)q[1].op*sum;
	
	
	fo(i,2,tot) {
		while (l>q[i].l) sub1(c[l--]);
		while (r<q[i].r) add2(c[++r]);
	
		while (l<q[i].l) add1(c[++l]);
		while (r>q[i].r) sub2(c[r--]);
		
		ans[q[i].id]+=(ll)q[i].op*sum;
		
//		printf("%lld\n",sum);
	}
	
	fo(i,1,m) printf("%lld\n",ans[i]);
	return 0;
	
}

 
 
 

标签:int,询问,tot,++,SNOI2017,include,sum,P5268,fo
From: https://www.cnblogs.com/ganking/p/17726697.html

相关文章

  • 【Azure Storage Account Table】询问批量将存储账户中的表嵌入另一个账户中的办法
    问题描述询问批量将存储账户中的表嵌入另一个账户中的办法? 问题解答方式一:使用 AzCopy 使用Azcopy做表格的导入导出,注意您需要使用Azcopy7.3版本来实现对Table的操作,可以选择导出到Blob中,这样导出的数据不会保存在本地,以及该指定支持并发导出。从表存储导出数据: htt......
  • L36_用日语询问时间
    语料地址概述用日语询问开始和结束的时间时,可以采用:~は、何時から、何時までですか?比如:明日の朝食は何時から、何時までですか明天的早饭从几点到几点?动画会话こちらのお部屋でございます这是二位的房间。お風呂は何時から何時までですか浴场从几点到几点开放?こ......
  • 树上询问
    #include<bits/stdc++.h>usingnamespacestd;constintN=1e6+5;intn,cnt,m,hd[N],c[N],l[N],r[N],d[N],ans[N];vector<int>q[N];structNode{intto,nxt;}edge[N];voidadd(intu,intv){edge[++cnt].to=v;edge[cnt].nxt......
  • L33_用日语询问需要等候多长时间
    语料地址概述在日语中,询问所需的时间,长度和距离或者数量的时候,可以采用疑问词:どのくらい,比如:どのくらいかかりますか需要多长时间?どのくらい待ちますか需要等候多长时间?动画会话どのくらい待ちますか要等多长时间?15分くらいです15分钟左右わかりました......
  • 前端学习笔记202305学习笔记第二十一天-vue3.0-使用messagebox组件询问用户是否可以删
       ......
  • 前端学习笔记202305学习笔记第二十一天-vue3.0-使用messagebox组件询问删除用户功能
      ......
  • 数列询问
    题目描述有一个长度为n的数列,数列中每个数都是[0,p-1]之间的整数。小明不知道数列中每个数的值,所以向小红做了m次询问。每次小明会向小红询问一个区间[l,r] 中所有数的和对p取模的结果。问完所有问题后,小明发现小红的回答中似乎存在矛盾。现在小明想找到最大的X,满足小......
  • windows打开此类文件前总是询问怎么解决
    打开此类文件前总是询问怎么解决这个一直提示的问题呢?下面来教大家一个方法杜绝再提示:开始-->运行-->gpedit.msc(组策略)-->用户配置-->管理模板-->windows组件-->附件管理器-->右击"中等危险文件类型的包含列表"-->属性-->选"已启用"-->在"指定中等危险......
  • L27_用日语询问最美味的食物是什么
    语料的视频观看地址概述日语中询问从几样东西选哪个好,可以用:どれが一番~か的句式,比如どれが一番美味しいですか哪个最好吃どれが一番有名ですか哪个最有名どれが一番安いですか?哪个最便宜动画会话ご注文は?需要点什么?タムさん、何にする?Tam,你想吃什么?どれ......
  • 【Azure 事件中心】Kafka 生产者发送消息失败,根据失败消息询问机器人得到的分析步骤
    问题描述AzureEventHubs--Kafka生产者发送消息存在延迟接收和丢失问题,在客户端的日志中发现如下异常:2023-06-0502:00:20.467[kafka-producer-thread|producer-1]ERRORcom.deloitte.common.kafka.CommonKafkaProducer-messageId:9235f334-e39f-b429-227e-45cd30dd6486......