1. cf 343 div2
求一个序列的最大上升子序列的和,比如 1 3 2 5 4 7,结果为 1 + 3 + 5 + 7 = 16;(本题要求严格递增)
设 F[i] 为以第 i 个数结尾的子序列的最大的和,则 F[i] = max(F[j] + a[i] (1 <= j <= i && a[j] < a[i]) ) 官方题解为: 把 a 排序并记录位置 p , 并建立线段树,节点值为 F[i] , 则 , F[i] = max(A[j].val) // 1 <= j <= p[i] ;
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <cstring> #include <cmath> #include <algorithm> using namespace std ; #define rep(i,n) for (int i = 1 ; i <= n ; ++ i) #define LL long long const int maxn = 100010 ; const double pi = acos(-1.0) ; struct Node { LL val ; int id ; friend bool operator < (const Node & P,const Node & T) { if (P.val == T.val) return T.id < P.id ; return P.val < T.val ; } }a[maxn] ; struct seg { int le , ri ; LL sc ; }A[maxn<<2]; int N , s[maxn] ; LL p[maxn] ; inline LL MAX(LL x,LL y) { if (x > y) return x ; else return y ; } void build(int i,int le,int ri) { A[i].le = le , A[i].ri = ri , A[i].sc = 0 ; if (le == ri) { s[le] = i ; return ; } int mid = (le + ri)/2 ; build(i<<1,le,mid) ; build(i<<1|1,mid+1,ri) ; } void update(int i,LL x) { i = s[i] ; A[i].sc = x ; while (i) { if (A[i].sc < x) A[i].sc = x ; i /= 2 ; } } LL query(int i,int le,int ri) { if (A[i].le == le && A[i].ri == ri) { return A[i].sc ; } int mid = (A[i].le + A[i].ri)/2 ; if (mid < le) return query(i<<1|1,le,ri) ; else if (ri <= mid) return query(i<<1,le,ri) ; else { return MAX(query(i<<1,le,mid),query(i<<1|1,mid+1,ri)) ; } } int main() { // freopen("in.txt","r",stdin) ; LL r , h , x ; scanf("%d",&N) ; rep(i,N) { scanf("%I64d%I64d",&r,&h) ; a[i].id = i , a[i].val = r*r*h ; // printf("%I64d ",a[i].val) ; } // puts("") ; sort(a+1,a+1+N) ; rep(i,N) { p[a[i].id] = i ; } build(1,1,N) ; rep(i,N) { update(p[i],a[p[i]].val + query(1,1,p[i])) ; } printf("%.10f\n",1.0*(double )A[1].sc*pi) ; return 0 ; }
2.cf edu round 9
题目大意: 给你一个 N 个数的数列 ,和一个 M ,求最小公倍数 gcd <= M 的 子序列,且要求子序列的长度最长。
( 1 <= N , M <= 1e6 ; 1 <= a[i] <= 1e9)
大于 M 的数可以直接去掉 , 用 cnt[x] 表示 x 出现的次数 , 枚举 gcd , 用 F[gcd] 表示最小公倍数为 gcd 时的子序列长度 , 则
F[gcd] 为 gcd 所有的因子的个数。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <cstring> #include <cmath> #include <algorithm> #include <vector> using namespace std ; #define rep(i,n) for (int i = 1 ; i <= n ; ++ i) #define LL long long const int maxn = 1000010 ; int cnt[maxn] , A[maxn] , N , M , F[maxn] ; int main() { // freopen("in.txt","r",stdin) ; scanf("%d%d",&N,&M) ; memset(cnt,0,sizeof(cnt)) ; memset(F,0,sizeof(F)) ; rep(i,N) { scanf("%d",&A[i]) ; if (A[i] <= M) cnt[A[i]] ++ ; } rep(i,M) { for (int j = i ; j <= M ; j += i) { F[j] += cnt[i] ; } } int id = 1 ; rep(i,M) { if (F[i] > F[id]) id = i ; } printf("%d %d\n",id,F[id]) ; rep(i,N) { if (id % A[i] == 0) printf("%d ",i) ; } puts("") ; return 0 ; }
3. 树状数组 hdu 1166 敌兵布阵
第一次写树状数组~~还不是很懂~觉得是好神奇的一种方法~看了下 这个博客,感觉讲得挺好的~~~orz......
本题只是点更新~~用树状数组代码好短~~~
4. <LCA _tarjan> poj 1986Distance Queries
lca 裸题~一次AC也是挺开心的&_&
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std ; 7 #define rep(i,n) for (int i = 1 ; i <= n ; ++ i) 8 const int maxn = 100010 ; 9 bool vis[maxn] ; 10 int h[maxn] , hq[maxn] , s[maxn] , anc[maxn] , dis[maxn] , ans[maxn] , cnt , cntq , n , r , q ; 11 struct Node 12 { 13 int nxt , w , to ; 14 }A[maxn],Q[maxn]; 15 16 void Init() 17 { 18 memset(vis,false,sizeof(vis)) ; 19 memset(h,-1,sizeof(h)) ; 20 memset(hq,-1,sizeof(hq)) ; 21 memset(ans,-1,sizeof(ans)) ; 22 memset(dis,0,sizeof(dis)) ; 23 rep(i,n) s[i] = anc[i] = i ; 24 cnt = cntq = 0 ; 25 } 26 27 inline void addedge(int u,int v,int w) 28 { 29 A[cnt].w = w , A[cnt].to = v ; 30 A[cnt].nxt = h[u] ; 31 h[u] = cnt ++ ; 32 } 33 34 inline void addask(int u,int v,int id) 35 { 36 Q[cntq].to = v , Q[cntq].w = id ; 37 Q[cntq].nxt = hq[u] ; 38 hq[u] = cntq ++ ; 39 } 40 41 inline int fi(int x) 42 { 43 int r = x , p = x , q ; 44 while (r != s[r]) r = s[r] ; 45 while (p != s[p]) { 46 q = s[p] ; 47 s[p] = r ; 48 p = q ; 49 } 50 return r ; 51 } 52 53 inline void join(int x,int y) 54 { 55 x = fi(x) , y = fi(y) ; 56 if (x != y) s[x] = y ; 57 } 58 59 void tarjan(int rt) 60 { 61 vis[rt] = true ; 62 int u ; 63 anc[rt] = rt ; 64 for (int i = h[rt] ; ~i ; i = A[i].nxt) { 65 u = A[i].to ; 66 if (!vis[u]) { 67 dis[u] = dis[rt] + A[i].w ; 68 tarjan(u) ; 69 join(u,rt) ; 70 anc[fi(u)] = rt ; 71 } 72 } 73 74 for (int i = hq[rt] ; ~i ; i = Q[i].nxt) { 75 u = Q[i].to ; 76 if (vis[u]) { 77 ans[Q[i].w] = dis[rt] + dis[u] - 2*dis[anc[fi(u)]] ; 78 } 79 } 80 } 81 82 int main() 83 { 84 int u , v , x ; 85 char c ; 86 // freopen("in.txt","r",stdin) ; 87 while (scanf("%d%d",&n,&r) == 2) { 88 Init() ; 89 rep(i,r) { 90 scanf("%d%d%d%c%c",&u,&v,&x,&c,&c) ; 91 addedge(u,v,x) ; 92 addedge(v,u,x) ; 93 // printf("%d %d %d %c\n",u,v,x,c) ; 94 } 95 scanf("%d",&q) ; 96 rep(i,q) { 97 scanf("%d%d",&u,&v) ; 98 addask(u,v,i) ; 99 addask(v,u,i) ; 100 } 101 tarjan(1) ; 102 rep(i,q) printf("%d\n",ans[i]) ; 103 } 104 return 0 ; 105 }
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <cstring> #include <algorithm> #include <cmath> using namespace std ; const int maxn = 50010 ; int c[maxn] , N ; void update(int k,int x) { while (k <= N) { c[k] += x ; k += (k&(-k)) ; } } inline int Query(int i) { int suma = 0 ; while (i) { suma += c[i] ; i -= (i&(-i)) ; } return suma ; } int main() { // freopen("in.txt","r",stdin) ; int T , kase = 1 , x , k ; char s[10] ; scanf("%d",&T) ; while (T --) { memset(c,0,sizeof(c)) ; scanf("%d",&N) ; for (int i = 1 ; i <= N ; ++ i) { scanf("%d",&x) ; update(i,x) ; } printf("Case %d:\n",kase++) ; while (scanf("%s",s) == 1) { if (s[0] == 'E') break ; else if (s[0] == 'A') { scanf("%d%d",&k,&x) ; update(k,x) ; } else if (s[0] == 'S') { scanf("%d%d",&k,&x) ; update(k,-x) ; } else if (s[0] == 'Q') { scanf("%d%d",&k,&x) ; printf("%d\n",Query(x)-Query(k-1)) ; } } } return 0 ; }
5. LCA st hdu 3078Network
题意:
给n个点Q个询问.// n <= 80000 ,Q <= 30000.
n个数,表示第 i 个点的权值.
一条边u , v
k u v // 如果k == 0 , val[u] = v , 否则查找u v 路径上权值的第 k 大.
思路:完全没思路,看了别人说的~居然是先求lca,然后直接暴力,如果是一条链,每次都问 k 1 n ~~完全不知道怎么搞
ps: u == v 时特殊处理一下~
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <cstring> 6 #include <cmath> 7 #include <vector> 8 using namespace std ; 9 #define rep(i,n) for (int i = 1 ; i <= n ; ++ i) 10 const int maxn = 80010 ; 11 int n , q ; 12 struct Node 13 { 14 int to , nxt ; 15 }A[maxn<<1]; 16 int fucc[maxn] ; 17 int h[maxn<<1] , cnt , ct , val[maxn] , fa[maxn] , ver[maxn<<1] , dep[maxn<<1] , pos[maxn] , st[maxn<<1][25] ; 18 bool vis[maxn] ; 19 20 inline void addedge(int u,int v) 21 { 22 A[cnt].to = v ; 23 A[cnt].nxt = h[u] ; 24 h[u] = cnt ++ ; 25 } 26 27 void dfs(int rt,int dis) 28 { 29 vis[rt] = true , ver[++ct] = rt ; 30 pos[rt] = ct , dep[ct] = dis ; 31 int u ; 32 for (int i = h[rt] ; ~i ; i = A[i].nxt) { 33 u = A[i].to ; 34 if (!vis[u]) { 35 fa[u] = rt ; 36 dfs(u,dis+1) ; 37 ver[++ct] = rt ; 38 dep[ct] = dis ; 39 } 40 } 41 } 42 43 void stBuild() 44 { 45 rep(i,ct) st[i][0] = i ; 46 int x , y , k ; 47 for (int j = 1 ; (1<<j) <= ct ; ++ j) { 48 k = (1<<j) ; 49 for (int i = 1 ; i+k-1 <= ct ; ++ i) { 50 x = st[i][j-1] , y = st[i+(1<<(j-1))][j-1] ; 51 st[i][j] = dep[x] < dep[y] ? x : y ; 52 } 53 } 54 } 55 56 inline int rmq(int le,int ri) 57 { 58 if (le > ri) swap(le,ri) ; 59 int k = (int )log2(ri-le+1.0) ; 60 if (le+(1<<(k+1))-1 <= ri) k ++ ; 61 int x = st[le][k] , y = st[ri-(1<<k)+1][k] ; 62 return (dep[x] < dep[y] ? x : y) ; 63 } 64 65 void Init() 66 { 67 memset(h,-1,sizeof(h)) ; 68 memset(vis,false,sizeof(vis)) ; 69 memset(val,0,sizeof(val)) ; 70 memset(fucc,0,sizeof(fucc)) ; 71 ct = cnt = 0 ; 72 fa[1] = 1 ; 73 } 74 75 int main() 76 { 77 // freopen("in.txt","r",stdin) ; 78 while (scanf("%d%d",&n,&q) == 2) { 79 Init() ; 80 rep(i,n) scanf("%d",&val[i]) ; 81 int u , v , k , kk ; 82 rep(i,n-1) { 83 scanf("%d%d",&u,&v) ; 84 addedge(u,v) ; 85 addedge(v,u) ; 86 } 87 dfs(1,1) ; 88 stBuild() ; 89 while (q --) { 90 scanf("%d%d%d",&k,&u,&v) ; 91 if (k == 0) { 92 val[u] = v ; 93 continue ; 94 } 95 kk = 0 ; 96 if (u == v) { 97 if(k==1)printf("%d\n",val[u]); 98 else printf("invalid request!\n"); 99 continue ; 100 } 101 else { 102 int LCA = ver[rmq(pos[u],pos[v])] ; 103 while (v != LCA) { 104 fucc[++kk] = val[v] ; 105 v = fa[v] ; 106 } 107 while (u != LCA) { 108 fucc[++kk] = val[u] ; 109 u = fa[u] ; 110 } 111 fucc[++kk] = val[LCA] ; 112 113 if (k > kk) puts("invalid request!") ; 114 else { 115 sort(fucc+1,fucc+1+kk) ; 116 printf("%d\n",fucc[kk-k+1]) ; 117 } 118 } 119 } 120 } 121 return 0 ; 122 }
6.lca_st hdu 5266 pog loves szh III
题意:
题意很清楚~求好多个点(从 li 到 ri) 的 LCA , 于是想到 LCA_ST ,和模板的区别在于要用线段树或其他方式处理 li -> ri 的最值.
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <iostream> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <cstring> 6 #include <algorithm> 7 #include <cmath> 8 #include <vector> 9 using namespace std ; 10 #define LL long long 11 #define rep(i,n) for (int i = 1;i <= n ; ++ i) 12 const int maxn = 300010 ; 13 int n , q ; 14 struct Node 15 { 16 int to , nxt ; 17 }A[maxn<<1]; 18 int ver[maxn<<1] , dep[maxn<<1] , pos[maxn] , h[maxn] , cnt , ct ; 19 bool vis[maxn] ; 20 21 inline void addedge(int u,int v) 22 { 23 A[cnt].nxt = h[u] ; 24 A[cnt].to = v ; 25 h[u] = cnt ++ ; 26 } 27 28 void dfs(int rt,int dis) 29 { 30 vis[rt] = true ; 31 ver[++ct] = rt ; 32 pos[rt] = ct ; 33 dep[ct] = dis ; 34 int u ; 35 for (int i = h[rt]; ~i ; i = A[i].nxt) { 36 u = A[i].to ; 37 if (!vis[u]) { 38 dfs(u,dis+1) ; 39 ver[++ct] = rt ; 40 dep[ct] = dis ; 41 } 42 } 43 } 44 45 int st[maxn<<1][20] ; 46 void stbuild() 47 { 48 rep(i,ct) st[i][0] = i ; 49 int k , x, y ; 50 for (int j = 1 ; (1 << j) <= ct ; ++ j) { 51 k = 1<<j ; 52 for (int i = 1 ; i+k-1<=ct ; ++ i) { 53 x = st[i][j-1] , y = st[i+(1<<(j-1))][j-1] ; 54 st[i][j] = dep[x] < dep[y] ? x : y ; 55 } 56 } 57 } 58 59 inline int rmq(int le,int ri) 60 { 61 if (le > ri) swap(le,ri) ; 62 int k = 0; 63 while((1<<k+1)<=ri-le+1) k++; 64 int x = st[le][k] , y = st[ri-(1<<k)+1][k] ; 65 return dep[x] < dep[y] ? x : y ; 66 } 67 68 struct fucc 69 { 70 int le , ri , ma , mi ; 71 }D[maxn<<2]; 72 int s[maxn] ; 73 74 void segbuild(int i,int le,int ri) 75 { 76 D[i].le = le , D[i].ri = ri ; 77 D[i].ma = 0 , D[i].mi = (maxn<<2) ; 78 if (le == ri) { 79 s[le] = i ; 80 return ; 81 } 82 int mid = (le+ri)/2 ; 83 segbuild(i<<1,le,mid) ; 84 segbuild(i<<1|1,mid+1,ri) ; 85 } 86 87 inline void update(int i,int x) 88 { 89 i = s[i] ; 90 if (D[i].ma < x) D[i].ma = x ; 91 if (D[i].mi > x) D[i].mi = x ; 92 i /= 2 ; 93 while (i) { 94 D[i].ma = (D[i<<1].ma > D[i<<1|1].ma ? D[i<<1].ma : D[i<<1|1].ma) ; 95 D[i].mi = (D[i<<1].mi < D[i<<1|1].mi ? D[i<<1].mi : D[i<<1|1].mi) ; 96 i /= 2 ; 97 } 98 } 99 100 inline int querymin(int i,int le,int ri) 101 { 102 if (D[i].le == le && D[i].ri == ri) return D[i].mi ; 103 int mid = (D[i].le + D[i].ri)/2 ; 104 if (ri <= mid) return querymin(i<<1,le,ri) ; 105 else if (le > mid) return querymin(i<<1|1,le,ri) ; 106 else { 107 int x = querymin(i<<1,le,mid) ; 108 int y = querymin(i<<1|1,mid+1,ri) ; 109 return (x < y ? x : y) ; 110 } 111 } 112 113 inline int querymax(int i,int le,int ri) 114 { 115 if (D[i].le == le && D[i].ri == ri) return D[i].ma ; 116 int mid = (D[i].le + D[i].ri)/2 ; 117 if (ri <= mid) return querymax(i<<1,le,ri) ; 118 else if (le > mid) return querymax(i<<1|1,le,ri) ; 119 else { 120 int x = querymax(i<<1,le,mid) ; 121 int y = querymax(i<<1|1,mid+1,ri) ; 122 return (x > y ? x : y) ; 123 } 124 } 125 126 void Init() 127 { 128 memset(h,-1,sizeof(h)) ; 129 memset(vis,false,sizeof(vis)) ; 130 ct = cnt = 0 ; 131 } 132 133 int main() 134 { 135 // freopen("in.txt","r",stdin) ; 136 int u , v , ma , mi ; 137 while (scanf("%d",&n) == 1) { 138 Init() ; 139 rep(i,n-1) { 140 scanf("%d%d",&u,&v) ; 141 addedge(u,v) ; 142 addedge(v,u) ; 143 } 144 dfs(1,1) ; 145 stbuild() ; 146 segbuild(1,1,n) ; 147 rep(i,n) update(i,pos[i]) ; 148 scanf("%d",&q) ; 149 while (q --) { 150 scanf("%d%d",&u,&v) ; 151 ma = querymax(1,u,v) ; 152 mi = querymin(1,u,v) ; 153 printf("%d\n",ver[rmq(mi,ma)]); 154 } 155 } 156 return 0 ; 157 }