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(); } }
题意:每次只能去栈顶元素于距离小于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(); } }