洛谷 P6006 [USACO20JAN]Farmer John Solves 3SUM G
洛谷 P6006 [USACO20JAN]Farmer John Solves 3SUM G
Problem
什么是3-SUM?
给你一个序列\(a\),求有多少组\((i,j,k)(1\le i<j<k\le n)\)满足\(a_i+a_j+a_k=0\).
这是一个有名的算法问题,尚未发现比运行速度比平方时间明显更优的解法。
这道题给你一个长度为\(n(n\le5000)\)的序列,之后有\(q(q\le10^6)\)个询问,查询你区间\([l,r]\)的\(3-SUM\)的答案。
Solution
当你看到题目描述的时候,可能会想那位Farmer John的重大突破是啥。但是你只要知道怎么\(O(n^2)\),再想想这个\(O(n^2)\)能不能预处理,然后用更低的时间复杂度查询就好。(别以为真的有啥接近线性的算法)
首先怎么\(O(n^2)\)做呢?
枚举两个变量,对当前的第三个变量的能取的范围预先开好一个桶计数。这样我们就固定了两个变量\(i,j\),去桶里面找\(-a_i-a_j\)的数量即可。
如果你是枚举\(i,j\),对k的取值范围\([j+1,n]\)开桶的话,当然也可以但是这个k的限制并不显然(或者是也有向下做的方法只是我没有想到吧)
如果我们枚举\(i,k\),这样\(k\)的取值范围就是\([i+1,k-1]\)。记\(c_x\)表示在当前区间内,等于\(x\)的\(a_k\)的数量;设\(f_{i,k}\)表示选定左端点为\(i\),右端点为\(k\)时的3-SUM方案数。
for(int i=1;i<=n;i++)
{
c[a[i+1]+M]++;
for(int k=i+2;k<=n;k++)
{
if(a[i]+a[k]<=M&&a[i]+a[k]>=-M) f[i][k]+=c[M-a[i]-a[k]];
c[a[k]+M]++;
}
c[a[i+1]+M]--;
for(int k=i+2;k<=n;k++)
{
c[a[k]+M]--;//clear
}
}
代码中的c是桶,M可以先不管(见下文)
对于一个询问\((l,r)\),这里的\(i,k\)当然可以选\([l,r]\)中的任意值(只要满足\(i<k\))。这不就是求
\]
这部分可以用二维前缀和预处理出来。
这样对于每一个询问都可以\(O(1)\)回答了。
需要注意的地方
不需要在求二维前缀和的时候判断\(i<k\)(准确说是\(i<\dots<k\Rightarrow i+1<k\)),因为不合法部分的\(f_{i,k}\)依然是\(0\).
即直接预处理
\]
对于每个询问用二维前缀和的差分
\]
就好了。
以及注意值域有负数,所以桶的大小要开两倍并且给所有的数都加上一个\(10^6\)。
Code
/**************************************************************
* Problem: 6006
* Author: Vanilla_chan
* Date: 20210307
**************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
#ifdef ONLINE_JUDGE
char buf[1<<23],* p1=buf,* p2=buf,obuf[1<<23],* O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
using namespace std;
template<class T>inline void read(T& x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)) { x=x*10+ch-'0';ch=getchar(); }
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)) { x=x*10+ch-'0';ch=getchar(); }
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do { G[++g]=x%10;x/=10; } while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
#define N 6010
int n,q;
int a[N];
LL f[N][N];
int c[2000010];
#define M 1000000
int main()
{
n=read();
q=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++)
{
c[a[i+1]+M]++;
for(int k=i+2;k<=n;k++)
{
if(a[i]+a[k]<=M&&a[i]+a[k]>=-M) f[i][k]+=c[M-a[i]-a[k]];
c[a[k]+M]++;
}
c[a[i+1]+M]--;
for(int k=i+2;k<=n;k++)
{
c[a[k]+M]--;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
}
}
int x,y;
while(q--)
{
x=read();
y=read();
if(x>y) swap(x,y);
write(f[y][y]-f[x-1][y]-f[y][x-1]+f[x-1][x-1]);
}
return 0;
}
洛谷 P6006 [USACO20JAN]Farmer John Solves 3SUM G的更多相关文章
- 洛谷 P2882 [USACO07MAR]Face The Right Way G
题目传送门 题目描述 Farmer John has arranged his N (1 ≤ N ≤ 5,000) cows in a row and many of them are facing ...
- 洛谷P2891 Dining P1402 酒店之王【类二分图匹配】题解+代码
洛谷P2891 Dining P1402 酒店之王[类二分图匹配]题解+代码 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的 ...
- 洛谷 P1596 [USACO10OCT]湖计数Lake Counting
题目链接 https://www.luogu.org/problemnew/show/P1596 题目描述 Due to recent rains, water has pooled in vario ...
- 洛谷 [USACO17OPEN]Bovine Genomics G奶牛基因组(金) ———— 1道骗人的二分+trie树(其实是差分算法)
题目 :Bovine Genomics G奶牛基因组 传送门: 洛谷P3667 题目描述 Farmer John owns NN cows with spots and NN cows without ...
- 洛谷P2982 [USACO10FEB]慢下来Slowing down(线段树 DFS序 区间增减 单点查询)
To 洛谷.2982 慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows con ...
- 洛谷 1938 [USACO09NOV]找工就业Job Hunt
洛谷 1938 [USACO09NOV]找工就业Job Hunt 题目描述 Bessie is running out of money and is searching for jobs. Far ...
- 洛谷 2953 [USACO09OPEN]牛的数字游戏Cow Digit Game
洛谷 2953 [USACO09OPEN]牛的数字游戏Cow Digit Game 题目描述 Bessie is playing a number game against Farmer John, ...
- 【洛谷】P2880 [USACO07JAN]平衡的阵容Balanced Lineup(st表)
题目背景 题目描述: 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连 ...
- 洛谷 P3659 [USACO17FEB]Why Did the Cow Cross the Road I G
//神题目(题目一开始就理解错了)... 题目描述 Why did the cow cross the road? Well, one reason is that Farmer John's far ...
- [洛谷P2852] [USACO06DEC]牛奶模式Milk Patterns
洛谷题目链接:[USACO06DEC]牛奶模式Milk Patterns 题目描述 Farmer John has noticed that the quality of milk given by ...
随机推荐
- dig命令命令常见用法
域名结构 主机名.次级域名.域名.根域名 host. sld .tld .root 几种常见的解析类型 A记录 CNAME txt记录 dig命令命令常见用法 dig,"domain inf ...
- 2025年我用 Compose 写了一个 Todo App
标题党嫌疑犯实锤 序言 从2月12日到3月4日这整整三周时间里,我从零开始又学习了一次 Compose. 为什么说又,是因为这已经是我第二次学习这套课程了. 故事从 4 年前说起,2021 年在意外获 ...
- Qt Oracle往数据库里插入或者更新图片
文章目录 Qt Oracle往数据库里插入或者更新图片 前言 读取本地图片文件 QPixmap 转 QByteArray 组成SQL,并执行 Qt Oracle往数据库里插入或者更新图片 前言 最近遇 ...
- WebScoket-服务器客户端双向通信
WebScoket学习笔记 1. 消息推送常用方式介绍 轮询 浏览器以指定的时间间隔向服务器发出HTTP请求,服务器实时返回数据给浏览器. 长轮询 浏览器发出ajax请求,服务器端接收到请求后,会阻塞 ...
- Alibaba Sentinel SSRF漏洞分析(CVE-2021-44139)
Alibaba Sentinel SSRF漏洞分析(CVE-2021-44139) 一.Alibaba Sentienl 简介 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel ...
- godoc使用方法介绍
一.go doc简介 Godoc是go语言的文档化工具,类似于文档化工具godoc,类似于Python的Docstring和Java的Javadoc Godoc通过解析包含注释的Go代码来生成HTML ...
- 认识webRTC
什么是 WebRTC 2010 年 5 月,谷歌收购了 Global IP Solutions(简称 GIPS),这是一家专注于 VoIP 和视频会议软件的公司,已开发出 RTC 所需的多项关键组件, ...
- APEX实战第2篇:构建自己第一个APEX程序
为了尽快实现从0到1的突破,第一个程序就选择一个最简单易懂的生活场景. 后续随着APEX学习过程不断迭代增强这个程序. 现在就开始吧,我给孩子看一些公开网络课时,习惯把课程资源做分片,然后有计划的让孩 ...
- Object类--equals方法--java进阶day05
1.equals方法 2.equals方法的逻辑 如图,我们发现调用equals方法将两个属性一样的变量进行比较时,返回的还是false 为了了解清楚equals方法的逻辑,我们ctrl 鼠标右键点击 ...
- 记载火狐浏览器下的一次新手级的js解密工作
警告:该随笔内容仅用于合法范围下的学习,不得用于任何商业和非法用途,不得未经授权转载,否则后果自负. 首先是需要解密的网站:https://www.aqistudy.cn/historydata/mo ...