题意

f(u,v):x小于等于u且y小于等于v的点才对f有贡献,每个这样的点贡献(u-x)+()

思路

=f(u_2,v_2)" class="mathcode" src="https://private.codecogs.com/gif.latex?u_1%20%5Cge%20u_2%20%5C%3B%20and%20%5C%3B%20v_1%20%5Cge%20v_2%20%5Cquad%20%5CRightarrow%20%5Cquad%20f%28u_1%2Cv_1%29%3E%3Df%28u_2%2Cv_2%29">

且等号当且仅当时取。

因此对于输入的0)" class="mathcode" src="https://private.codecogs.com/gif.latex?C%28C%3E0%29">,对于1个特定的,至多有一个似的. (标号①)

当我们固定一个变量的时候,关于另一个变量是单调的(标号②)

因此,我选择横竖两条线移动。

初始状态u=0,v=N.此时f值显然过小。

对于一个状态,

如果f过小,则只能往竖线右调,f才可能增大。

如果f过大,则只能横线往下调。

如果f刚好,答案计数加1,同时,这个u已经不可能有v符合了。往右调(其实往下调也行,关键是要固定一种走法)。

f过小时,v往上调是没有意义的,因为初始状态是v所能取的最大值(N),能到达目前的状态,是从前面的太大或者已经计数过的答案状态转移过来的。往上调就是是走回头路,回去要不就是f过大,要不就是已经计数了的恰好等于f的状态。

同理,f过大时,竖线左调是没有意义的。

同时根据(标号①)的结论易证,不会有情况疏漏掉。

换句话说,如此移动,不重不漏,至多移动2N次。

具体可以参考C++源码

注意,getCount不要用二分,直接枚举就好了。

二分反而会更慢,慢原因是二分需要先排序,排序是,是排序数组片段长度。

而注意到getCount(u,v)每一个u至多查询1次,直接枚举是,反而复杂度更低。

复杂度估计,由于每个片段至多查询一次,且最坏情况下所有片段都查询了。因此对于一个输入C,总的复杂度是.

有个2倍是因为对反过来的rp也要考虑。

因此总复杂度是

不考虑系数,大概带入数字算一下。不超过20*10*10^5+(1000-20)*10*10^4=1.18*10^8.

4s时间限制是OK的。

源码

java(Tle)

java一开始我的java jdk时1.8.ZOJ评测时1.7.莫名RE

后来用1.7,还是莫名RE.

最后故意加死循环,提交。二分测试发现ZOJ Java switch不支持枚举型变量。黑人问号。

最后无奈改成if语句,然后从Re变成Tle了。根据网上的进行了输入输出优化还是不行。

import java.util.*;
import java.io.*;
public class Main {
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) {
try {
cin.nextToken();
int cnt = (int) cin.nval;
LittleSubAndHisGeometryProblem p;
for (int i = 0;i < cnt; ++i) {
p = new LittleSubAndHisGeometryProblem();
p.run();
}
cout.flush();
} catch (Exception e) { }
}
} class LittleSubAndHisGeometryProblem{
final int N;
int pointCnt;
PointsSys normal;
PointsSys reverse;
int queryCnt; LittleSubAndHisGeometryProblem() throws Exception { Main.cin.nextToken();
N = (int)Main.cin.nval; Main.cin.nextToken(); pointCnt = (int)Main.cin.nval; // 做准备工作,方便满足“a=a0,b<=b0的点的个数及他们的b之和”
normal = new PointsSys();
reverse = new PointsSys();
int x,y;
for (int i = 0;i < pointCnt; ++i) {
Main.cin.nextToken();
x = (int)Main.cin.nval;
Main.cin.nextToken();
y = (int)Main.cin.nval;
normal.add(x,y);
reverse.add(y,x);
} Main.cin.nextToken();
queryCnt = (int)Main.cin.nval;
} class PointSysQueryInfo{
int cnt = 0;
long sum = 0;
void add(long a) {
++cnt;
sum += a;
}
} class PointsSys{
int cnt;
ArrayList<ArrayList<Integer>> p; PointsSys() {
p = new ArrayList<ArrayList<Integer>>();
for (int i = 0;i <= N; ++i)
p.add(new ArrayList<Integer>());
} void add(int x,int y) {
p.get(x).add(y);
} void query(int x,int y,PointSysQueryInfo change) {
// 返回X值恰好为x,且Y值小于等于y的所有点的信息
// 返回点数和sigama(y-Yi) Yi取遍所有的满足要求的点的Y
change.cnt = 0;
change.sum = 0;
ArrayList<Integer> list = p.get(x);
for (int Y : list)
if (Y <= y)
change.add(y-Y);
}
} public enum Move{
Right,Down
} void count() {
// 求解符合题意的方案数
queryAns = 0;
if (2L*N*pointCnt <= c)
return;
int u = 0;
int v = N;
PointSysQueryInfo curr = new PointSysQueryInfo();
PointSysQueryInfo change = new PointSysQueryInfo();
Move moveFlag = Move.Right;
//boolean first = true;
while (u <= N && v > 0) {
if (curr.sum == c)
++queryAns;
if (moveFlag == Move.Right) { // Go Right
++u;
if (u > N) return;
normal.query(u, v ,change);
curr.sum += change.sum + curr.cnt;
curr.cnt += change.cnt;
} else { // Go Down
if (v <= 0) return;
reverse.query(v,u,change);
--v;
curr.cnt -= change.cnt;
curr.sum -= change.sum+curr.cnt;
}
if (curr.sum >= c)
moveFlag = Move.Down;
else
moveFlag = Move.Right;
}
return;
} long c;
int queryAns;
void run() throws Exception {
boolean first = true; for (int i = 0; i < queryCnt; ++i) { Main.cin.nextToken();
c = (long)Main.cin.nval; count();
if (first) {
Main.cout.print(queryAns);
first = false;
} else {
Main.cout.print(" "+queryAns);
}
}
Main.cout.println();
}
}

C++ (AC)

#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 100005;
int N,K;
vector<int>p[kMaxN];
vector<int>rp[kMaxN]; void getCount(vector<int>&p,int b,int &cnt,long long &s) {
cnt = 0;
s = 0;
for (auto y : p)
if (y <= b) {
++cnt;
s += b-y;
}
} int count(long long c) {
if (c >= 2ll*(long long)N*(long long)K)
return 0;
int u = 0;
int v = N;
int ans = 0;
bool isGoRight = true;
long long f,f0;
int cnt,cnt0;
f = 0; cnt = 0;
while (u <= N && v >= 1) {
if (f == c)
++ans;
if (isGoRight) { // Go Right
++u;
getCount(p[u],v,cnt0,f0);
f += f0+(long long)cnt;
cnt += cnt0;
} else { // Go Down
getCount(rp[v],u,cnt0,f0);
--v;
cnt -= cnt0;
f -= f0+(long long)cnt;
}
isGoRight = f < c;
}
return ans;
} void work() {
cin>>N>>K;
for (int i = 0; i <= N; ++i) {
p[i].clear();
rp[i].clear();
}
int x,y;
for (int i = 0;i < K; ++i) {
cin>>x>>y;
p[x].push_back(y);
rp[y].push_back(x);
}
int Q;
cin>>Q;
long long c;
int ans;
for (int i = 0; i < Q; ++i) {
cin>>c;
ans = count(c);
if (i)
cout<<' '<<ans;
else
cout<<ans;
}
cout<<'\n';
} int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while (T--)
work();
return 0;
}

ZOJ 4082 Little Sub and his Geometry Problem题解的更多相关文章

  1. ZOJ - 4082:Little Sub and his Geometry Problem (双指针)

    Little Sub loves math very much, and has just come up with an interesting problem when he is working ...

  2. ZOJ Monthly, January 2019 Little Sub and his Geometry Problem 【推导 + 双指针】

    传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5861 Little Sub and his Geometry Prob ...

  3. HDU1086You can Solve a Geometry Problem too(判断线段相交)

    You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/3 ...

  4. codeforces 361 E - Mike and Geometry Problem

    原题: Description Mike wants to prepare for IMO but he doesn't know geometry, so his teacher gave him ...

  5. hdu 1086 You can Solve a Geometry Problem too

    You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/3 ...

  6. CodeForces 689E Mike and Geometry Problem (离散化+组合数)

    Mike and Geometry Problem 题目链接: http://acm.hust.edu.cn/vjudge/contest/121333#problem/I Description M ...

  7. Codeforces Gym 100338B Geometry Problem 计算几何

    Problem B. Geometry ProblemTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudg ...

  8. you can Solve a Geometry Problem too(hdoj1086)

    Problem Description Many geometry(几何)problems were designed in the ACM/ICPC. And now, I also prepare ...

  9. (hdu step 7.1.2)You can Solve a Geometry Problem too(乞讨n条线段,相交两者之间的段数)

    称号: You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/ ...

随机推荐

  1. python os和sys模块使用

    python os和sys模块使用 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录:相 ...

  2. Linux 软件安装卸载 (源码、rpm)

    Linux下软件的安装主要有两种不同的形式.第一种安装为源码安装,文件名为xxx.tar.gz压缩包为主;以第一种方式发行的软件多为以源码形式发送的.第二种方式则是另一种安装文件名为xxx.i386. ...

  3. vue element 表头添加斜线

    <template> <div class="app-container"> <el-table :data="tableData3&quo ...

  4. Python学习小记(4)---class

    1.名称修改机制 大概是会对形如 __parm 的成员修改为 _classname__spam 9.6. Private Variables “Private” instance variables ...

  5. Android Studio 学习笔记(五):WebView 简单说明

    Android中一个用于网页显示的控件,实际上,也可以看做一个功能最小化的浏览器,看起来类似于在微信中打开网页链接的页面.WebView主要用于在app应用中方便地访问远程网页或本地html资源.同时 ...

  6. [MySQL] mysql索引的长度计算和联合索引

    1.所有的索引字段,如果没有设置not null,则需要加一个字节.2.定长字段,int占4个字节.date占3个字节.char(n)占n个字符.3.变长字段,varchar(n),则有n个字符+两个 ...

  7. myeclipce 按 Alt + / 代码提示无法感应自己定义的类 解决方案

    解决方案:如图把这些选项全部都勾选即可.(注意 :需先排除是不是快捷键冲突,我遇到的问题是Alt+/可以提示jdk内置的对象和方法,但是无法提示自定义的类和方法.如Alt+/无法提示任何信息 需重新设 ...

  8. GHM论文笔记(CVPR2019)

    目录 作者要解决的问题 Focal loss(CVPR2017) Focal loss的解决方案 Focal loss的不足 设计思路 梯度与样本的关系 梯度分布计算方法:将0-1的梯度切bin,计算 ...

  9. 声明式服务调用:Spring Cloud Feign

    最近在学习Spring Cloud的知识,现将声明式服务调用:Spring Cloud Feign 的相关知识笔记整理如下.[采用 oneNote格式排版]

  10. LeetCode 面试题 02.06. 回文链表

    题目链接:https://leetcode-cn.com/problems/palindrome-linked-list-lcci/ 编写一个函数,检查输入的链表是否是回文的. 示例 1: 输入: 1 ...