hdu 4267 A Simple Problem With Integers
题意:数列更新,每次更新区间[a,b]内a <= i <= b and (i - a) % k == 0的点Ai,讯问某个点的值。
解法:由于k较小,因此可以按k不同分别维护更新,最后累计更新量,对于一个固定的k,由于是等距更新,同一次更新中影响的点的下标除k的余数相同,因此按照余数将点归类就变成了更新连续区间,查询点的值,开一个10*10的树状数组的数组,tree[i][j]表示下标除i余j的点在k=i时的增量。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class changchun {
int maxn = 50010;
class IndexTree {
int ss[],N;
IndexTree(int maxn){
N=maxn;
ss=new int[maxn];
}
int lowbit(int k){
return (k&-k);
}
void init(){
Arrays.fill(ss,0);
}
void inc(int i,int k){
while(i<=N){
ss[i]+=k;
i+=lowbit(i);
}
}
int get(int i){
int res=0;
while(i>0){
res+=ss[i];
i-=lowbit(i);
}
return res;
}
void update(int left,int right,int v){
inc(left,v);
inc(right+1,-v);
}
}
IndexTree tree[][] = new IndexTree[12][12];
int arr[] = new int[maxn], n;
void run() throws IOException {
for(int i=1;i<=10;i++)
for(int j=0;j<i;j++)
tree[i][j]=new IndexTree(maxn/i+10);
while (in.nextToken() != in.TT_EOF) {
n = (int) in.nval;
for (int i = 1; i <= n; i++)
arr[i] = nextInt();
for(int i=1;i<=10;i++)
for(int j=0;j<i;j++)
tree[i][j].init();
int m = nextInt();
while (m-- > 0) {
int t = nextInt();
if (t == 1) {
int a = nextInt();
int b = nextInt();
int k = nextInt();
int c = nextInt();
int v = a % k;
int left = a / k;
if (v!= 0)
left++;
int right =left+(b-a)/k;
tree[k][v].update(left, right, c);
} else {
int p = nextInt();
int res = 0;
for (int i = 1; i <= 10; i++) {
int j=p%i;
if (j!=0)
res += tree[i][j].get(p / i + 1);
else
res += tree[i][j].get(p/i);
}
System.out.println(arr[p]+res);
}
}
}
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
public static void main(String[] args) throws IOException {
new changchun().run();
}
}
hdu 4268 Alice and Bob
题意:alice和bob各有n个矩形,问alice最多能覆盖多少个bob的矩形
解法:分别将两人的矩形先按w再按h排序,最小于alice[i]的w且没被覆盖过的bob的矩形中找一个h最大的覆盖,用TreeMap维护前驱即可。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.TreeMap;
public class Main{
class node implements Comparable<node> {
int x, y;
node(int a, int b) {
x = a;
y = b;
}
public int compareTo(node oth) {
if (x<oth.x)
return -1;
if (x==oth.x&&y <= oth.y)
return -1;
return 1;
}
}
class Tree {
TreeMap<Integer, Integer> tree = new TreeMap<Integer, Integer>();
void init() {
tree.clear();
}
void insert(int k) {
if (tree.containsKey(k))
tree.put(k, tree.get(k)+1);
else
tree.put(k, 1);
}
int poll(int k) {
if (tree.isEmpty()||tree.firstKey()>k)
return -1;
int res = tree.floorKey(k);
if (tree.get(res) == 1)
tree.remove(res);
else
tree.put(res, tree.get(res)-1);
return res;
}
}
Tree tree=new Tree();
node alice[] = new node[100010], bob[] = new node[100010];
void run() throws IOException {
int cas=nextInt();
while (cas-->0) {
int n = nextInt();
for (int i = 0; i < n; i++)
alice[i] = new node(nextInt(),nextInt());
for (int i = 0; i < n; i++)
bob[i] = new node(nextInt(),nextInt());
Arrays.sort(alice, 0, n);
Arrays.sort(bob, 0, n);
int res = 0,k= 0;
tree.init();
for (int i=0;i<n;i++) {
while(k<n&&bob[k].x<=alice[i].x)
tree.insert(bob[k++].y);
if(tree.poll(alice[i].y)!=-1)
res++;
}
System.out.println(res);
}
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
public static void main(String[] args) throws IOException {
new Main().run();
}
}
hdu 4272 LianLianKan
题意:每次只能去栈顶元素于距离小于5的元素相连,问是否能有将所有元素弹出。
解法:比赛时想到的那个贪心明显是错误的,比赛后交上竟然AC了,每次取距离最近的相同元素是显然不对的,数据太弱了。正确做法暂时还不会
hdu 4273 Rescue
模板题,听队友说poj有类似的,帖过来就A了,不懂。。。
hdu 4274 Spy's Work
题意:给出一棵树,每个节点有一个大于0的点权,给出若干条约束表示某节点子树权值和的范围,问着若干条约束是否相互矛盾。
解法:自底向上遍历,当一棵树的子树都遍历玩后统计出子树权值和的和的范围,与给出的比较看是否矛盾。若不矛盾两区间做交运算,进一步约束取值范围。注意可能有对一个点的多个约束。
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
public class Main{
int maxn = 10010;
long inf = 1l << 60;
class node {
int ne, be;
node(int b, int e) {
be = b;
ne = e;
}
}
node buf[] = new node[maxn * 2];
int E[] = new int[maxn], len;
void add(int a, int b) {
buf[len] = new node(b, E[a]);
E[a] = len++;
buf[len] = new node(a, E[b]);
E[b] = len++;
}
long max[] = new long[maxn], min[] = new long[maxn];
boolean vis[] = new boolean[maxn], flag;
void dfs(int a) {
vis[a] = true;
long left = 1,right=inf;
for (int i = E[a]; i != -1; i = buf[i].ne) {
int b = buf[i].be;
if (vis[b])
continue;
dfs(b);
left += min[b];
}
min[a] = Math.max(left, min[a]);
max[a] = Math.min(right, max[a]);
}
void init() {
len = 0;
flag = true;
Arrays.fill(E, -1);
Arrays.fill(vis, false);
Arrays.fill(min, 1);
Arrays.fill(max, inf);
}
Scanner scan = new Scanner(System.in);
void run() {
while (scan.hasNext()) {
int n = scan.nextInt();
init();
for (int i = 2; i <= n; i++)
add(scan.nextInt(), i);
int m = scan.nextInt();
while (m-- > 0) {
int a = scan.nextInt();
String s = scan.next();
int b = scan.nextInt();
if (s.charAt(0) == '='){
min[a]=Math.max(min[a], b);
max[a]=Math.min(max[a], b);
}
if (s.charAt(0) == '>')
min[a]=Math.max(min[a], b+1);
if (s.charAt(0) == '<')
max[a]=Math.min(max[a], b-1);
}
dfs(1);
for(int i=1;i<=n;i++)
if(min[i]>max[i])
flag=false;
if (flag)
System.out.println("True");
else
System.out.println("Lie");
}
}
public static void main(String[] args) throws IOException {
new Main().run();
}
}
hdu 4276 The Ghost Blows Light
题意:一棵树上每个点有一个财富值,每条边有耗时,现要在T时间内从1走到n,问最大获益。
解法:首先树形DP,dp[a][t]表示从a节点出发发挥t时间回到a节点的最大获益,利用背包原理进行状态转移,然后选出1到n路径上的点进行一次背包dp2[i][j]表示路径上前i个点花费j时间的最大获利,若1到n的距离为dis,则dp2[n][T-dis]即是答案,复杂度O(NT*T),被卡住了搞了好多次才赖过,应该不是正解。。。
hdu 4277 USACO ORZ
题意:给出n根木棍,问能组成多少个不同的三角形(三条边长度不完全相等)
解法:3^15枚举所有方案,若abc三条边能构成三角形且a<=b<=c,则使用RK哈希函数将这个三角形映射到一个值,然后利用HashSet去重
import java.util.HashSet;
import java.util.Scanner;
public class Triangle {
int a,b,c;
int arr[]=new int[1010],n,sum;
long M=200010;
HashSet<Long> mp=new HashSet<Long>();
void dfs(int d){
if(d>n){
if(a+b>c&&a+c>b&&b+c>a){
int x=Math.min(a,Math.min(b,c));
int y=Math.max(a,Math.max(b,c));
mp.add(x+(a+b+c-x-y)*M+y*M*M);
}
return;
}
sum-=arr[d];
a+=arr[d];
dfs(d+1);
a-=arr[d];
b+=arr[d];
dfs(d+1);
b-=arr[d];
c+=arr[d];
dfs(d+1);
c-=arr[d];
}
Scanner scan=new Scanner(System.in);
void run(){
int cas=scan.nextInt();
while(cas-->0){
n=scan.nextInt();
sum=0;
for(int i=1;i<=n;i++){
arr[i]=scan.nextInt();
sum+=arr[i];
}
a=b=c=0;
mp.clear();
dfs(1);
System.out.println(mp.size());
}
}
public static void main(String[] args){
new Triangle().run();
}
}