次方计数的拆贡献法(考虑组合意义)+限定类问题善用值域与位置进行ds:1006T3

对于多次方的计数问题可以考虑拆贡献。

题目问 ∣ S ∣ 3 |S|^3 S3 ∣ S ∣ |S| S 表示选的点数。相当于在 ∣ S ∣ |S| S 中选了3次,也就是选了3个可相同的点。

先考虑3个不相同点的贡献,对应任意3个点,必然会对所有包含其矩形产生贡献。所以只需要统计对应的矩形数目。但是必须乘上全排列6,因为我们钦定选了3次是考虑顺序的。

对于2个同,3个同同理。都会对相应矩形产生贡献。

现在考虑统计3个点的情况,发现本质有两种:
在这里插入图片描述
这种很好统计,直接ds维护。

在这里插入图片描述

这种我们拿ds维护的时候,很容易出现算错的现象。因为我们计算贡献的顺序可能是这样的:

在这里插入图片描述

那就会把这种情况算进去:

在这里插入图片描述

而用这种方法计算则不会出现问题,因为我们放在了两边

在这里插入图片描述

//5.7k#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||
ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
//mt19937 rand(time(0));
//mt19937_64 rand(time(0));
//srand(time(0));
#define N 100010
//#define M
#define mo 998244353
struct Node {int x, id; 
}b[N];
int n, m, i, j, k, T;
int ans1, ans2, ans3; 
int mx, p[N], a[N], rt; int calc1() {int ans=0; for(i=1; i<=n; ++i) {ans+=i*(n-i+1)%mo*p[i]%mo*(n-p[i]+1)%mo; ans%=mo; }return ans; 
}void Add(int &a, int b) {a+=b; a%=mo; 
}void Mul(int &a, int b) {a*=b; a%=mo; 
}struct Binary_tree {int cnt[N], i; void clear() {for(i=0; i<=n; ++i) cnt[i]=0; }void add(int x, int y) {
//		printf("> %d\n", x); while(x<=n) Add(cnt[x], y), x+=x&-x; }int que(int x) {
//				printf("> %d\n", x); int ans=0; while(x) Add(ans, cnt[x]), x-=x&-x; return ans; }
}Bin, Bin1, Bin2;int suan() {int i, ans=0; Bin.clear(); for(i=1; i<=n; ++i) {Add(ans, Bin.que(a[i])*(n-i+1)%mo*(n-a[i]+1)%mo);  Bin.add(a[i], a[i]*i%mo); }return ans; 
}int calc2() {int ans=0; ans+=suan(); for(i=1; i<=n; ++i) a[i]=n-a[i]+1; ans+=suan(); ans%=mo; return ans; 
}int suan31() {int ans=0, i; Bin1.clear(); Bin2.clear(); for(i=1; i<=n; ++i) Bin2.add(a[i], (n-i+1)*(n-a[i]+1)%mo); for(i=1; i<=n; ++i) {Bin2.add(a[i], -(n-i+1)*(n-a[i]+1)%mo); Add(ans, Bin1.que(a[i])*(Bin2.que(n)-Bin2.que(a[i]))); 
//		printf("%lld : %lld\n", i, ans); Bin1.add(a[i], i*a[i]%mo); }return ans; 
}struct Segment_tree {int tot, ls[N<<2], rs[N<<2]; int s[N<<2], c[N<<2], tag[N<<2]; void clear(int &k, int l, int r) {if(!k) k=++tot, s[k]=c[k]=tag[k]=ls[k]=rs[k]=0; if(l==r) return ; int mid=(l+r)>>1; clear(ls[k], l, mid); clear(rs[k], mid+1, r); }void push_down(int k) {Add(tag[ls[k]], tag[k]); Add(tag[rs[k]], tag[k]); Add(s[ls[k]], c[ls[k]]*tag[k]%mo); Add(s[rs[k]], c[rs[k]]*tag[k]%mo); tag[k]=0; }void push_up(int k) {s[k]=(s[ls[k]]+s[rs[k]])%mo; c[k]=(c[ls[k]]+c[rs[k]])%mo; }void add(int k, int l, int r, int x, int y) {
//		printf("Add : %lld %lld\n", x, y); if(l==r) {Add(c[k], y);
//			printf("Then c[%lld] become %lld\n", k, c[k]); return  void(); }
//		printf("s[%lld]=%lld [%lld %lld]\n", k, s[k], x, y); push_down(k); 
//		printf("s[%lld]=%lld [%lld %lld]\n", k, s[k], x, y); int mid=(l+r)>>1; if(x<=mid) add(ls[k], l, mid, x, y); else add(rs[k], mid+1, r, x, y);
//		printf("s[%lld]=%lld [%lld %lld]\n", k, s[k], x, y); push_up(k); 
//		printf("s[%lld]=%lld [%lld %lld]\n", k, s[k], x, y); 
//		printf("Then c[%lld] become %lld\n", k, c[k]); }void modify(int k, int l, int r, int x, int y, int z) {if(l>=x && r<=y) {Add(s[k], c[k]*z%mo), Add(tag[k], z); 
//			printf("==== [%lld] %lld %lld\n", k, s[k], c[k]); 
//			return Add(s[k], c[k]*z%mo), Add(tag[k], z), void();return ;  }int mid=(l+r)>>1; push_down(k);  if(x<=mid) modify(ls[k], l, mid, x, y, z); if(y>=mid+1) modify(rs[k], mid+1, r, x, y, z); push_up(k); 
//		printf(">>> s[%lld]=%lld [%lld %lld]\n", k, s[k], x, y); //		printf("")}int que(int k, int l, int r, int x, int y) {if(l>=x && r<=y) return s[k]; int mid=(l+r)>>1, sum=0; push_down(k); if(x<=mid) sum+=que(ls[k], l, mid, x, y); if(y>=mid+1) sum+=que(rs[k], mid+1, r, x, y); return sum%mo; }
}Seg;int suan32() {int ans=0, i; 
//	for(i=1; i<=n; ++i) printf("%lld ", a[i]); printf(" => "); 
	Bin1.clear(); Bin2.clear(); 
//	for(i=1; i<=n; ++i) {
//		Add(ans, (n-i+1)*Bin2.que(a[i])%mo); 
//		printf("%lld : %lld %lld\n", (n-i+1)*Bin2.que(a[i]), a[i]*(Bin1.que(n)-Bin1.que(a[i]))); 
//		Bin2.add(a[i], a[i]*(Bin1.que(n)-Bin1.que(a[i]))%mo); 
//		Bin1.add(a[i], i*(n-a[i]+1)%mo); 
//	}for(i=1; i<=n; ++i) b[i].x=a[i], b[i].id=i; sort(b+1, b+n+1, [] (Node x, Node y) { return x.x>y.x; }); rt=Seg.tot=0; Seg.clear(rt, 1, n); for(i=1; i<=n; ++i) {Add(ans, b[i].x*(n-b[i].id+1)%mo*Seg.que(1, 1, n, 1, b[i].id)%mo); 
//		printf("%lld[%lld %lld] : %lld %lld %lld\n", i, 
//			b[i].id, b[i].x, b[i].x*(n-b[i].id+1), Seg.que(1, 1, n, 1, b[i].id), 
//					b[i].x*(n-b[i].id+1)%mo*Seg.que(1, 1, n, 1, b[i].id)%mo); Seg.modify(1, 1, n, b[i].id, n, b[i].id); Seg.add(1, 1, n, b[i].id, n-b[i].x+1); }
//	printf("%lld\n", ans); return ans; 
}int calc3() {int ans=0, i; memcpy(a, p, sizeof(a)); Add(ans, suan31()); for(i=1; i<=n; ++i) a[i]=n-a[i]+1; Add(ans, suan31()); 
//	printf("%lld (%lld)\n", ans, ans*6); memcpy(a, p, sizeof(a)); Add(ans, suan32()); reverse(a+1, a+n+1); Add(ans, suan32()); for(i=1; i<=n; ++i) a[i]=n-a[i]+1; Add(ans, suan32()); reverse(a+1, a+n+1); Add(ans, suan32()); 
//	printf("%lld (%lld)\n", ans, ans*6); return ans; 
//	return 0; 
}signed main()
{
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);freopen("points.in", "r", stdin);freopen("points.out", "w", stdout);
//	T=read();
//	while(T--) {
//
//	}	n=read(); mx=read(); for(i=1; i<=n; ++i) p[i]=a[i]=read(); ans1=calc1(); ans2=calc2(); ans3=calc3(); 
//	printf("Basic : %lld\n", ans1+ans2*6); if(mx==1) return printf("%lld ", ans1), 0; if(mx==2) return printf("%lld ", (ans1+2*ans2)%mo), 0; if(mx==3) return printf("%lld ", (ans1+6*ans2+6*ans3)%mo), 0; return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/95964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【小工具-生成合并文件】使用python实现2个excel文件根据主键合并生成csv文件

1 小工具说明 1.1 功能说明 一般来说&#xff0c;我们会先有一个老的文件&#xff0c;这个文件内容是定制好相关列的表格&#xff0c;作为每天的报告。 当下一天来的时候&#xff0c;需要根据新的报表文件和昨天的报表文件做一个合并&#xff0c;合并的时候就会出现有些事新增…

【BI看板】Superset2.0+图表二次开发初探

Superset图表功能也很丰富了&#xff0c;但一些个性化的定制需求就需要二次开发了。网上二开的superset版本大多是0.xxx版本的或1.5xxx版本&#xff0c;本次用的是2.xxx。 源码相关说明 源码目录 superset-2.0\superset-frontend\plugins\plugin-chart-echarts 插件相关资料 官…

【重拾C语言】六、批量数据组织(二)线性表——分类与检索(主元排序、冒泡排序、插入排序、顺序检索、对半检索)

目录 前言 六、批量数据组织——数组 6.4 线性表——分类与检索 6.4.1 主元排序 6.4.2 冒泡排序 6.4.3 插入排序 6.4.4 顺序检索&#xff08;线性搜索&#xff09; 6.4.5 对半检索&#xff08;二分查找&#xff09; 算法比较 前言 线性表是一种常见的数据结构&#xf…

在linux下预览markdown的方法,转换成html和pdf

背景 markdown是一种便于编写和版本控制的格式&#xff0c;但却不便于预览——特别是包含表格等复杂内容时&#xff0c;单纯的语法高亮是远远不够的——这样就不能边预览边调整内容&#xff0c;需要找到一种预览方法。 思路 linux下有个工具&#xff0c;叫pandoc&#xff0c…

Go Gin Gorm Casbin权限管理实现 - 2. 使用Gorm存储Casbin权限配置以及`增删改查`

文章目录 0. 背景1. 准备工作2. 权限配置以及增删改查2.1 策略和组使用规范2.2 用户以及组关系的增删改查2.2.1 获取所有用户以及关联的角色2.2.2 角色组中添加用户2.2.3 角色组中删除用户 2.3 角色组权限的增删改查2.3.1 获取所有角色组权限2.3.2 创建角色组权限2.3.3 修改角色…

Spring MVC工作原理

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Qt model/view 理解01

在 Qt 中对数据处理主要有两种方式&#xff1a;1&#xff09;直接对包含数据的的数据项 item 进行操作&#xff0c;这种方法简单、易操作&#xff0c;现实方式单一的缺点&#xff0c;特别是对于大数据或在不同位置重复出现的数据必须依次对其进行操作&#xff0c;如果现实方式改…

10.1select并发服务器以及客户端

服务器&#xff1a; #include<myhead.h>//do-while只是为了不让花括号单独存在&#xff0c;并不循环 #define ERR_MSG(msg) do{\fprintf(stderr,"%d:",__LINE__);\perror(msg);\ }while(0);#define PORT 8888//端口号1024-49151 #define IP "192.168.2.5…

【16】c++设计模式——>建造者(生成器)模式

什么是建造者模式? 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许你构造复杂对象步骤分解。你可以不同的步骤中使用不同的方式创建对象&#xff0c;且对象的创建与表示是分离的。这样&#xff0c;同样的构建过程可以创建不同的表…

数据结构-快速排序-C语言实现

引言&#xff1a;快速排序作为一种非常经典且高效的排序算法&#xff0c;无论是工作还是面试中广泛用到&#xff0c;作为一种分治思想&#xff0c;需要熟悉递归思想。下面来讲讲快速排序的实现和改进。 老规矩&#xff0c;先用图解来理解一下&#xff1a;&#xff08;这里使用快…

MATLAB中syms函数使用

目录 语法 说明 示例 创建符号标量变量 创建符号标量变量的向量 创建符号标量变量矩阵 管理符号标量变量的假设 创建和评估符号函数 syms函数的作用是创建符号标量和函数&#xff0c;以及矩阵变量和函数。 语法 syms var1 ... varN syms var1 ... varN [n1 ... nM] …

指数分布优化器(EDO)(含MATLAB代码)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

“秋天第一只大闸蟹”背后,看见京东一体化供应链

京东似乎正在从一个大闸蟹的物流服务商、销售商&#xff0c;转变为一个大闸蟹的“供货商”。 作者|斗斗 编辑|皮爷 出品|产业家 阳澄湖连续几天的降雨&#xff0c;使得通往蟹塘的路异常难走。 长期驻扎此地的京东相关负责人蹲在蟹塘边的小路上&#xff0c;指着蟹塘说道…

【RabbitMQ 实战】08 集群原理剖析

上一节&#xff0c;我们用docker-compose搭建了一个RabbitMQ集群&#xff0c;这一节我们来分析一下集群的原理 一、基础概念 1.1 元数据 前面我们有介绍到 RabbitMQ 内部有各种基础构件&#xff0c;包括队列、交换器、绑定、虚拟主机等&#xff0c;他们组成了 AMQP 协议消息…

Cocos Creator3.8 项目实战(五)背景无限滚屏效果如何实现

在游戏中&#xff0c;我们经常会实现背景无限滚动的效果。那这些效果是怎么实现的呢&#xff1f; 原理很简单&#xff0c;就是使用多张背景图&#xff0c;每张图&#xff0c;每一帧都同时移动&#xff0c;当图移出屏幕外时&#xff0c;将其位置设置到下一张图的初始位置&#x…

【AI视野·今日NLP 自然语言处理论文速览 第四十八期】Thu, 5 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 5 Oct 2023 Totally 50 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Retrieval meets Long Context Large Language Models Authors Peng Xu, Wei Ping, Xianchao Wu, Lawrence McA…

[架构之路-231]:计算机硬件与体系结构 - 性能评估汇总,性能优化加速比

目录 一、计算机体系结构 二、计算机性能评估 2.1 分类方法1 2.2 分类方法2 三、常见的专项性能测试工具 3.1 浮点运算性能&#xff08;FLOPS&#xff09; 3.2 综合理论性能法 3.3 历史基准测试&#xff08;跑分软件&#xff09;&#xff1a;通过运行典型的综合性的程序…

反爬虫机制与反爬虫技术(一)

反爬虫机制与反爬虫技术一 1、网络爬虫的法律与道德问题2、反爬虫机制与反爬虫技术2.1、User-Agent伪装2.2、代理IP2.3、请求频率控制2.4、动态页面处理2.5、验证码识别3、反爬虫案例:豆瓣电影Top250爬取3.1、爬取目标3.2、库(模块)简介3.3、翻页分析3.4、发送请求3.5、提取…

【VUE·疑难问题】定义 table 中每行的高度(使用 element-UI)

一、如何定义 table 中每一行的 height &#xff1f; 1.table例子 <!-- 二、table --><div style"overflow: hidden;display: block;height: 68vh;width: 100%;"><el-table stripe show-header style"width: 100%" :data"tableData&q…

mysql面试题20:有哪些合适的分布式主键方案

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:有哪些合适的分布式主键方案? UUID:UUID通常是由一个二进制的128位整数表示,可以保证全局的唯一性。在Java中,可以通过UUID类生成一个UUID。例…