线段树·二

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 }
View Code

 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 }
View Code

 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 }
View Code
原文地址:https://www.cnblogs.com/ivan-count/p/7465904.html