1、UVA 11525 Permutation
题意:求1~k这k个数中第N个排列。(N从0开始记)。N=sum(Si*(k-i)!)(1≤i≤k)
思路:根据N的值的性质,联系康拓展开,不妨发现第i位的值为剩下没用的数中从小到大第Si+1个。可以用线段树来记录区间内没有用的数的个数。
1 #include<iostream> 2 using namespace std; 3 int k; 4 const int maxk = 50010; 5 int numk[maxk]; 6 int tree[maxk << 2]; 7 void Build(int root, int l, int r) 8 { 9 if (l == r) 10 { 11 tree[root] = 1; 12 return; 13 } 14 int mid = (l + r) / 2; 15 Build(root * 2, l, mid); 16 Build(root * 2 + 1, mid + 1, r); 17 tree[root] = tree[root * 2] + tree[root * 2 + 1]; 18 } 19 int pos; 20 void Query(int root, int l, int r, int x) 21 { 22 if (l == r) 23 { 24 tree[root] = 0; 25 pos = l; 26 return; 27 } 28 int mid = (l + r) / 2; 29 if (x <= tree[root*2]) Query(root * 2, l, mid, x); 30 else Query(root * 2 + 1, mid + 1, r, x - tree[root * 2]); 31 tree[root] = tree[root * 2] + tree[root * 2 + 1]; 32 } 33 int main() 34 { 35 int t; 36 scanf("%d", &t); 37 while (t--) 38 { 39 scanf("%d", &k); 40 Build(1, 1, k); 41 for (int i = 1; i <= k; i++) 42 { 43 int num; 44 scanf("%d", &num); 45 if (i > 1) printf(" "); 46 pos = 0; 47 Query(1, 1, k, num + 1); 48 printf("%d", pos); 49 } 50 printf(" "); 51 } 52 return 0; 53 }
2、LA 4730 Kingdom
题意:每次可以连接两个城市,或询问纵坐标为y的直线所穿过的城市群及其总的城市数目。
思路:用并查集维护每个城市群的最大y值、最小y值、城市数;由于询问的纵坐标的值始终小数部分为0.5,那么我们把每个城市群的最小y值+1,所询问纵坐标向上取整。
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 100100;//最多城市数 7 const int maxy = 1000100;//y坐标最大值 8 struct node 9 { 10 int states; 11 int citys; 12 int addst; 13 int addct; 14 }tree[maxy<<2]; 15 16 int vy[maxn];//存每个城市的y坐标 17 int pre[maxn];//存祖先 18 int maxh[maxn];//存连通块的最大y值 19 int minh[maxn];//存连通块的最小y值 20 int cnt[maxn];//存连通块的城市数目 21 int Find(int x) 22 { 23 if (x == pre[x]) return x; 24 else 25 { 26 int fa = pre[x]; 27 pre[x] = Find(fa); 28 return pre[x]; 29 } 30 } 31 void PushDown(int root, int l, int r) 32 { 33 if (tree[root].addct!=0) 34 { 35 tree[root * 2].citys += tree[root].addct; 36 tree[root * 2+1].citys += tree[root].addct; 37 tree[root * 2].addct += tree[root].addct; 38 tree[root * 2 + 1].addct += tree[root].addct; 39 tree[root].addct = 0; 40 } 41 if (tree[root].addst!=0) 42 { 43 tree[root * 2].states += tree[root].addst; 44 tree[root * 2 + 1].states += tree[root].addst; 45 tree[root * 2].addst += tree[root].addst; 46 tree[root * 2 + 1].addst += tree[root].addst; 47 tree[root].addst = 0; 48 } 49 } 50 void Build(int root, int l, int r) 51 { 52 tree[root].citys = tree[root].states = tree[root].addct = tree[root].addst = 0; 53 if(l==r)return; 54 int mid = (l + r) / 2; 55 Build(root * 2, l, mid); 56 Build(root * 2 + 1, mid + 1, r); 57 } 58 void Update(int root, int l, int r, int ul, int ur, int v, int flag) 59 {//flag=1,addcity;flag=2,addstate 60 if (l > ur || r < ul) return; 61 if (l >= ul&&r <= ur) 62 { 63 if (flag == 1) 64 { 65 tree[root].citys += v; 66 tree[root].addct += v; 67 } 68 else 69 { 70 tree[root].states += v; 71 tree[root].addst += v; 72 } 73 return; 74 } 75 PushDown(root, l, r); 76 int mid = (l + r) / 2; 77 Update(root * 2, l, mid, ul, ur, v, flag); 78 Update(root * 2 + 1, mid + 1, r, ul, ur, v, flag); 79 } 80 pair<int, int> Query(int root, int l, int r, int posy) 81 { 82 //if (l > posy || r < posy) return make_pair(0, 0); 83 if (l == r&&l == posy) 84 { 85 return make_pair(tree[root].states, tree[root].citys); 86 } 87 PushDown(root, l, r); 88 int mid = (l + r) / 2; 89 if (posy <= mid) return Query(root * 2, l, mid, posy); 90 else return Query(root * 2 + 1, mid + 1, r, posy); 91 } 92 void Union(int u, int v) 93 { 94 int fu = Find(u), fv = Find(v); 95 if (fu != fv) 96 { 97 if (minh[fu] < maxh[fu]) 98 { 99 Update(1, 0, maxy - 1, minh[fu] + 1, maxh[fu], -cnt[fu], 1); 100 Update(1, 0, maxy - 1, minh[fu] + 1, maxh[fu], -1, 2); 101 } 102 if (minh[fv] < maxh[fv]) 103 { 104 Update(1, 0, maxy - 1, minh[fv] + 1, maxh[fv], -cnt[fv], 1); 105 Update(1, 0, maxy - 1, minh[fv] + 1, maxh[fv], -1, 2); 106 } 107 if (fu > fv) swap(fu, fv);//约定以小的为祖先 108 pre[fv] = fu; 109 minh[fu] = min(minh[fu], minh[fv]); 110 maxh[fu] = max(maxh[fu], maxh[fv]); 111 cnt[fu] += cnt[fv]; 112 Update(1, 0, maxy - 1, minh[fu] + 1, maxh[fu], cnt[fu], 1); 113 Update(1, 0, maxy - 1, minh[fu] + 1, maxh[fu],1, 2); 114 } 115 } 116 void Solve() 117 { 118 int n; 119 scanf("%d", &n); 120 int x; 121 for (int i = 0; i < n; i++) scanf("%d%d", &x, &vy[i]); 122 Build(1, 0, maxy - 1); 123 for (int i = 0; i < n; i++) pre[i] = i, maxh[i] = vy[i], minh[i] = vy[i], cnt[i] = 1; 124 int q; 125 scanf("%d", &q); 126 char s[10]; 127 while (q--) 128 { 129 scanf("%s", s); 130 if (s[0] == 'r') 131 { 132 int u, v; 133 scanf("%d%d", &u, &v); 134 Union(u, v); 135 } 136 else 137 { 138 double posy; 139 scanf("%lf", &posy); 140 pair<int, int>ans = Query(1, 0, maxy - 1,int(posy+1)); 141 printf("%d %d ", ans.first, ans.second); 142 } 143 } 144 } 145 int main() 146 { 147 int t; 148 scanf("%d", &t); 149 while (t--) 150 { 151 Solve(); 152 } 153 return 0; 154 }
3、LA 5694/UVA 1492/hdu 4052 Adding New Machine
题意:w*h大小的房间一些矩形区域已经有物品,现在要放一个1*m大小的物品,问有多少种放法。
思路:分横着和竖着考虑。以横着为例,每个矩形区域右侧m-1区域放不了,以及0~m-1位置放不了。用总面积减去这样所有的矩形面积并则是横着的方案数。竖着类似。注意n==0和m==1的情况。
1 #include <iostream> 2 #include <vector> 3 #include <cmath> 4 #include <map> 5 #include <cstdio> 6 #include <algorithm> 7 using namespace std; 8 9 typedef long long ll; 10 11 const int maxn = 51000; 12 struct node 13 { 14 int l, r, pos, c; 15 node(int l0 = 0, int r0 = 0, int pos0 = 0, int c0 = 0) 16 { 17 l = l0, r = r0, pos = pos0; c = c0; 18 } 19 friend bool operator < (node a, node b) 20 { 21 return a.pos<b.pos; 22 } 23 }; 24 25 struct rec 26 { 27 int x1, y1, x2, y2; 28 }d[maxn]; 29 30 31 vector <node> v; 32 int w, h, m, n; 33 vector <int> c; 34 map <int, int> mp; 35 36 struct Tree 37 { 38 int l, r, cover, len; 39 }tree[8 * maxn]; 40 41 void build(int l, int r, int k) 42 { 43 tree[k].l = l; 44 tree[k].r = r; 45 tree[k].len = 0; 46 tree[k].cover = 0; 47 if (l + 1 >= r) return; 48 int mid = (l + r) >> 1; 49 build(l, mid, k << 1); 50 build(mid, r, k << 1 | 1); 51 } 52 53 void pushup(int root) 54 { 55 if (tree[root].cover>0) tree[root].len = c[tree[root].r] - c[tree[root].l]; 56 else if (tree[root].l + 1 == tree[root].r) tree[root].len = 0; 57 else tree[root].len = tree[root << 1].len + tree[root << 1 | 1].len; 58 } 59 60 void insert(int l, int r, int root, int c0) 61 { 62 if (l <= tree[root].l && tree[root].r <= r) 63 { 64 tree[root].cover += c0; 65 } 66 else 67 { 68 int mid = (tree[root].l + tree[root].r) >> 1; 69 if (r <= mid) insert(l, r, root << 1, c0); 70 else if (l >= mid) insert(l, r, root << 1 | 1, c0); 71 else 72 { 73 insert(l, mid, root << 1, c0); 74 insert(mid, r, root << 1 | 1, c0); 75 } 76 } 77 pushup(root); 78 } 79 80 ll getans() 81 { 82 if (v.size() <= 0) return (ll)w*(ll)h; 83 c.clear(); 84 mp.clear(); 85 sort(v.begin(), v.end()); 86 for (int i = 0; i<v.size(); i++) 87 { 88 mp[v[i].l] = i; 89 mp[v[i].r] = i; 90 } 91 for (map <int, int>::iterator it = mp.begin(); it != mp.end(); it++) 92 { 93 it->second = c.size(); 94 c.push_back(it->first); 95 } 96 ll ret = 0; 97 build(0, c.size() - 1, 1); 98 insert(mp[v[0].l], mp[v[0].r], 1, v[0].c); 99 for (int i = 1; i<v.size(); i++) 100 { 101 ret += (ll)(v[i].pos - v[i - 1].pos)*(ll)tree[1].len; 102 insert(mp[v[i].l], mp[v[i].r], 1, v[i].c); 103 } 104 return (ll)w*(ll)h - ret; 105 } 106 107 void solve() 108 { 109 v.clear(); 110 for (int i = 0; i<n; i++) 111 { 112 v.push_back(node(max(d[i].x1 + 1 - m, 0), d[i].x2, d[i].y1, 1)); 113 v.push_back(node(max(d[i].x1 + 1 - m, 0), d[i].x2, d[i].y2, -1)); 114 } 115 if (m>1) 116 { 117 v.push_back(node(max(0, w + 1 - m), w, 0, 1)); 118 v.push_back(node(max(0, w + 1 - m), w, h, -1)); 119 } 120 121 ll ans = getans(); 122 123 if (m == 1) 124 { 125 printf("%lld ", ans); 126 return; 127 } 128 129 v.clear(); 130 for (int i = 0; i<n; i++) 131 { 132 v.push_back(node(max(d[i].y1 + 1 - m, 0), d[i].y2, d[i].x1, 1)); 133 v.push_back(node(max(d[i].y1 + 1 - m, 0), d[i].y2, d[i].x2, -1)); 134 } 135 if (m>1) 136 { 137 v.push_back(node(max(0, h + 1 - m), h, 0, 1)); 138 v.push_back(node(max(0, h + 1 - m), h, w, -1)); 139 } 140 ans += getans(); 141 printf("%lld ", ans); 142 } 143 144 int main() 145 { 146 while (scanf("%d%d%d%d", &w, &h, &n, &m) != EOF) 147 { 148 for (int i = 0; i<n; i++) 149 { 150 scanf("%d%d%d%d", &d[i].x1, &d[i].y1, &d[i].x2, &d[i].y2); 151 d[i].x1--; d[i].y1--; 152 } 153 solve(); 154 } 155 return 0; 156 }