题目大意:
给你N个数字,和一个数字t,求满足l<=r,a[l] + a[l+1] + …… + a[r] < t 的(l,r)对数。
思路
首先考虑a[l] + a[l+1] + …… + a[r]应该用sum[r] - sum[l - 1]直接求得,那么对于每一个sum[i],我们要求的就是sum[j] > sum[i] - t (1 <= j <= i - 1) 的j的个数。想到的是每次处理完sum[i],都要把sum[i]添加到数据结构中,还要方便查找小于某一数字的节点个数。前者添加最优的是链表,后者查找最优的有序数组,综合一下就是树了。我在这里用的是二叉平衡数,做完之后想了一下,感觉可能用优先队列那样的树可能更合适,写起来更方便。
代码实现
i 从 1 到 n
对于当前 i,查找树中的大于sum[i] - t的个数,这样就求出了满足sum[i] - sum[j] < t 的j的个数。
找完之后,将sum[i]添加到树中。
这里有个问题,平衡二叉树一般不插入同值节点,但是题目里有可能,所以要处理一下。节点应该要保存的信息有:节点值,节点值的个数(为了解决同值问题),左子树所有节点的节点值个数加上当前节点值个数的和(有点绕口,理解起来就是小于等于当前节点值的sum[j]的j的个数,不过这里有同值,节点信息里多了个值的个数,说起来绕口)
丑陋的代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main1042D {
static class Node {
public int height;
public long value;
public Node parent;
public Node leftSon;
public Node rightSon;
public int valueCount;
public int count;
public Node(long v) {
value = v;
height = 1;
parent = null;
leftSon = null;
rightSon = null;
count = 1;
valueCount = 1;
}
public void calculateCount() {
int count = 0;
if (null != leftSon)
count += leftSon.count;
if (null != rightSon)
count += rightSon.count;
this.count = count + valueCount;
}
public void calculatorHeight() {
int leftHeight = 0;
int rightHeight = 0;
if (null != leftSon)
leftHeight = leftSon.height;
if (null != rightSon)
rightHeight = rightSon.height;
this.height = Math.max(leftHeight, rightHeight) + 1;
}
}
static Node root;
public static void main(String[] args) throws IOException {
StreamTokenizer streamTokenizer = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
streamTokenizer.nextToken();
int n = (int) streamTokenizer.nval;
streamTokenizer.nextToken();
long t = (long) streamTokenizer.nval;
long x;
long count = 0;
root = new Node(0);
Node temp;
long ans = 0;
for (int i = 0; i < n; i++) {
streamTokenizer.nextToken();
x = (long) streamTokenizer.nval;
count += x;
temp = new Node(count);
ans += find(count - t);
addNode(root, temp);
}
System.out.println(ans);
}
public static void addNode(Node cur, Node node) {
if (cur.value < node.value) {
if (null == cur.rightSon) {
node.parent = cur;
cur.rightSon = node;
} else
addNode(cur.rightSon, node);
}
else if (cur.value > node.value) {
if (null == cur.leftSon) {
node.parent = cur;
cur.leftSon = node;
}
else
addNode(cur.leftSon, node);
} else {
cur.valueCount++;
cur.count++;
}
int leftHeight = 0;
int rightHeight = 0;
int leftHeight2 = 0;
int rightHeight2 = 0;
if (null != cur.leftSon)
leftHeight = cur.leftSon.height;
if (null != cur.rightSon)
rightHeight = cur.rightSon.height;
if (leftHeight > rightHeight + 1) { //左边高
if (null != cur.leftSon.leftSon)
leftHeight2 = cur.leftSon.leftSon.height;
if (null != cur.leftSon.rightSon)
rightHeight2 = cur.leftSon.rightSon.height;
if (leftHeight2 > rightHeight2) //左左
rightTranslate(cur);
else { //左右
leftTranslate(cur.leftSon);
rightTranslate(cur);
}
}
else if (rightHeight > leftHeight + 1) {//右边高
if (null != cur.rightSon.leftSon)
leftHeight2 = cur.rightSon.leftSon.height;
if (null != cur.rightSon.rightSon)
rightHeight2 = cur.rightSon.rightSon.height;
if (leftHeight2 > rightHeight2) { //右左
rightTranslate(cur.rightSon);
leftTranslate(cur);
}
else //右右
leftTranslate(cur);
}
else {
cur.height = Math.max(leftHeight, rightHeight) + 1;
cur.calculateCount();
}
}
public static void leftTranslate(Node node) {
Node rightSon = node.rightSon;
node.rightSon = rightSon.leftSon;
if (null != node.rightSon)
node.rightSon.parent = node;
rightSon.leftSon = node;
if (null == node.parent)
root = rightSon;
else if (node.parent.leftSon == node)
node.parent.leftSon = rightSon;
else
node.parent.rightSon = rightSon;
rightSon.parent = node.parent;
node.parent = rightSon;
node.calculateCount();
rightSon.calculateCount();
node.calculatorHeight();
rightSon.calculatorHeight();
}
public static void rightTranslate(Node node) {
Node leftSon = node.leftSon;
node.leftSon = leftSon.rightSon;
if (null != node.leftSon)
node.leftSon.parent = node;
leftSon.rightSon = node;
if (null == node.parent)
root = leftSon;
else if (node.parent.leftSon == node)
node.parent.leftSon = leftSon;
else
node.parent.rightSon = leftSon;
leftSon.parent = node.parent;
node.parent = leftSon;
node.calculateCount();
leftSon.calculateCount();
node.calculatorHeight();
leftSon.calculatorHeight();
}
public static int find(long v) {
Node node = root;
int result = 0;
while (null != node) {
if (node.value > v) {
if (null != node.rightSon)
result += node.rightSon.count;
result += node.valueCount;
node = node.leftSon;
} else
node = node.rightSon;
}
return result;
}
}
写的不好,欢迎指教23333