次方计数的拆贡献法(考虑组合意义)+限定类问题善用值域与位置进行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.hqwc.cn/news/126118.html

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

相关文章

【GO 编程语言】面向对象

指针与结构体 文章目录 指针与结构体一、OOP 思想二、继承三、方法四、接口实现五、多态六、空接口七、接口继承八、接口断言九、Type别名 一、OOP 思想 Go语言不是面向对象的语言&#xff0c;这里只是通过一些方法来模拟面向对象&#xff0c;从而更好的来理解面向对象思想 面…

什么,这年头还有人不知道404

写在前面 哥&#xff0c;来帮我看看&#xff0c;这个请求怎么404了&#xff0c;明明接口路径是对的啊&#xff01;一个下午&#xff0c;组里的小哥突然让我帮忙看这个问题&#xff0c;我不禁一惊&#xff0c;啥&#xff0c;这年头了还有人搞不定404&#xff0c;如有还有&#…

国庆中秋宅家自省: Python在Excel中绘图尝鲜

Python3中类的高级语法及实战 Python3(基础|高级)语法实战(|多线程|多进程|线程池|进程池技术)|多线程安全问题解决方案 Python3数据科学包系列(一):数据分析实战 Python3数据科学包系列(二):数据分析实战 Python3数据科学包系列(三):数据分析实战 【一】国庆中秋: 悟 【国…

[React源码解析] React的设计理念和源码架构 (一)

任务分割异步执行让出执法权 文章目录 1.React的设计理念1.1 Fiber1.2 Scheduler1.3 Lane1.4 代数效应 2.React的源码架构2.1 大概图示2.2 jsx2.3 Fiber双缓存2.4 scheduler2.5 Lane模型2.6 reconciler2.7 renderer2.8 concurrent 3.React源码调试 1.React的设计理念 Fiber: 即…

SpringMVC+统一表现层返回值+异常处理器

一、统一表现层返回值 根据我们不同的处理方法&#xff0c;返回的数据格式都会不同&#xff0c;例如添加只返回true|false&#xff0c;删除同理&#xff0c;而查询却返回数据。 Result类 为此我们封装一个result类来用于表现层的返回。 public class Result {//描述统一格式…

【二】spring boot-设计思想

spring boot-设计思想 简介&#xff1a;现在越来越多的人开始分析spring boot源码&#xff0c;拿到项目之后就有点无从下手了&#xff0c;这里介绍一下springboot源码的项目结构 一、项目结构 从上图可以看到&#xff0c;源码分为两个模块&#xff1a; spring-boot-project&a…

【程序员必看】计算机网络,快速了解网络层次、常用协议和物理设备!

文章目录 0 引言1 基础知识的定义1.1 计算机网络层次1.2 网络供应商 ISP1.3 猫、路由器、交换机1.4 IP协议1.5 TCP、UDP协议1.6 HTTP、HTTPS、FTP协议1.7 Web、Web浏览器、Web服务器1.8 以太网和WLAN1.9 Socket &#xff08;网络套接字&#xff09; 2 总结 0 引言 在学习的过程…

【Go语言实战】(25) 分布式算法 MapReduce

MapReduce 写在前面 身为大数据专业的学生&#xff0c;其实大学我也多多少少接触过mapreduce&#xff0c;但是当时觉得这玩意太老了&#xff0c;觉得这和php一样会被时代淘汰。只能说当时确实太年轻了&#xff0c;没有好好珍惜那时候的学习资源… 现在回过头来看mapreduce&a…

如何选择合适的自动化测试工具?

自动化测试是高质量软件交付领域中最重要的实践之一。在今天的敏捷开发方法中&#xff0c;几乎任一软件开发过程都需要在开发阶段的某个时候进行自动化测试&#xff0c;以加速回归测试的工作。自动化测试工具可以帮助测试人员以及整个团队专注于自动化工具无法处理的各自任务&a…

练[watevrCTF-2019]Cookie Store

[watevrCTF-2019]Cookie Store 文章目录 [watevrCTF-2019]Cookie Store掌握知识解题思路关键paylaod 掌握知识 ​ 抓包放包&#xff0c;set-cookie和cookie的联系&#xff0c;base64编码&#xff0c;cookie请求头 解题思路 打开题目链接&#xff0c;发现响应速度有点慢。发现…

【AI视野·今日Robot 机器人论文速览 第四十九期】Fri, 6 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Fri, 6 Oct 2023 Totally 29 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;ContactGen, 基于生成模型的抓取手势生成&#xff0c;类人五指手。(from 伊利诺伊大学 香槟) 数据集&#xff1a;GRAB da…

使用Visual Studio调试排查Windows系统程序audiodg.exe频繁弹出报错

VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&a…