2012长春网络赛(hdu4267 hdu4268 hdu4274 hdu4276 hdu4277)

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();
	}
}


你可能感兴趣的:(c,网络,String,tree,Class,import)