15.3.22湖南省多校对抗

http://acm.csu.edu.cn/OnlineJudge/contest.php?cid=2070

比赛是组队赛,居然弄了一个第三名,现场第二,醉了

多亏队友们的齐心协力,全部1A,出的题不是最多但是比较快没有罚时~

赛后自己把题目又重新A了一遍。

A:CSU1536N比较小,直接暴力搜索一遍

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <vector>
 8 #include <cstdio>
 9 #include <cctype>
10 #include <cstring>
11 #include <cstdlib>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 #define INF 0x3f3f3f3f
16 #define inf (-((LL)1<<40))
17 #define lson k<<1, L, mid
18 #define rson k<<1|1, mid+1, R
19 #define mem0(a) memset(a,0,sizeof(a))
20 #define mem1(a) memset(a,-1,sizeof(a))
21 #define mem(a, b) memset(a, b, sizeof(a))
22 #define FIN freopen("in.txt", "r", stdin)
23 #define FOUT freopen("out.txt", "w", stdout)
24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
25  
26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
32  
33 //typedef __int64 LL;
34 typedef long long LL;
35 const int MAXN = 1010;
36 const int MAXM = 2000010;
37 const double eps = 1e-4;
38  
39 int n, m;
40 struct Node {
41     int arr[16], step;
42 }s;
43 int tar[20], vis[1 << 16];
44  
45 int conv(Node a) {
46     int ret = 0;
47     rep (i, 0, n - 1) {
48         ret <<= 1;
49         ret |= a.arr[i];
50     }
51     return ret;
52 }
53  
54 int getEnd(Node a) {
55     int cnt = 1, id = 0;
56     rep (i, 1, n - 1) {
57         if(a.arr[i] == a.arr[i - 1]) cnt ++;
58         else {
59             if(cnt != tar[id]) return 0;
60             cnt = 1; id ++;
61         }
62     }
63     return cnt == tar[id];
64 }
65  
66 int bfs()
67 {
68     mem0(vis);
69     queue<Node>q;
70     s.step = 0;
71     vis[conv(s)] = 1;
72     q.push(s);
73     while(!q.empty()) {
74         Node fr = q.front(); q.pop();
75         if(getEnd(fr)) return fr.step;
76         rep (i, 0, n - 2) {
77             Node tail = fr;
78             swap(tail.arr[i], tail.arr[i + 1]);
79             if(!vis[conv(tail)]) {
80                 tail.step = fr.step + 1;
81                 q.push(tail);
82                 vis[conv(tail)] = 1;
83             }
84         }
85     }
86     return 0;
87 }
88  
89 int main()
90 {
91     //FIN;
92     while(~scanf("%d %d", &n, &m)) {
93         rep (i, 0, n - 1) scanf("%d", &s.arr[i]);
94         rep (i, 0, m - 1) scanf("%d", &tar[i]);
95         cout << bfs() << endl;
96     }
97     return 0;
98 }
View Code

B:CSU1537模拟一遍

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <vector>
 8 #include <cstdio>
 9 #include <cctype>
10 #include <cstring>
11 #include <cstdlib>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 #define INF 0x3f3f3f3f
16 #define inf (-((LL)1<<40))
17 #define lson k<<1, L, mid
18 #define rson k<<1|1, mid+1, R
19 #define mem0(a) memset(a,0,sizeof(a))
20 #define mem1(a) memset(a,-1,sizeof(a))
21 #define mem(a, b) memset(a, b, sizeof(a))
22 #define FIN freopen("in.txt", "r", stdin)
23 #define FOUT freopen("out.txt", "w", stdout)
24 #define rep(i, a, b) for(int i = a; i <= b; i +=2)
25  
26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
32  
33 //typedef __int64 LL;
34 typedef long long LL;
35 const int MAXN = 1010;
36 const int MAXM = 2000010;
37 const double eps = 1e-4;
38  
39 char s[200];
40 int res;
41  
42 int equals1() {
43     stack<int>st;
44     st.push(s[0] - '0');
45     int len = strlen(s);
46     rep (i, 1, len-1) {
47         if(s[i] == '+') st.push(s[i + 1] - '0');
48         else st.top() = st.top() * (s[i + 1] - '0');
49     }
50     int ret = 0;
51     while(!st.empty()) {
52         ret += st.top(); st.pop();
53     }
54     return ret == res;
55 }
56  
57 int equals2() {
58     int len = strlen(s), ret = s[0] - '0';
59     rep (i, 1, len-1) {
60         if(s[i] == '+') ret += s[i + 1] - '0';
61         else ret *= s[i + 1] - '0';
62     }
63     return ret == res;
64 }
65  
66 int main()
67 {
68     //FIN;
69     while(cin >> s >> res) {
70         int ans1 = equals1(), ans2 = equals2();
71         if(ans1) {
72             if(ans2) puts("U");
73             else puts("M");
74         }
75         else {
76             if(ans2) puts("L");
77             else puts("I");
78         }
79     }
80     return 0;
81 }
View Code

C:CSU1538分析一遍发现要走最少的路程,应该如果有交叉的区间,直接合并为一个大的区间,即若(a1, b1)与(a2, b2)满足a1 < a2,若a2 <= b1那么将其合并为(a1, b2)即应从a1走到b2再回到a1(这时就访问了b1与a2),再去到b2,证明也是可以证明的。

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <vector>
 8 #include <cstdio>
 9 #include <cctype>
10 #include <cstring>
11 #include <cstdlib>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 #define INF 0x3f3f3f3f
16 #define inf (-((LL)1<<40))
17 #define lson k<<1, L, mid
18 #define rson k<<1|1, mid+1, R
19 #define mem0(a) memset(a,0,sizeof(a))
20 #define mem1(a) memset(a,-1,sizeof(a))
21 #define mem(a, b) memset(a, b, sizeof(a))
22 #define FIN freopen("in.txt", "r", stdin)
23 #define FOUT freopen("out.txt", "w", stdout)
24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
25  
26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
32  
33 //typedef __int64 LL;
34 typedef long long LL;
35 const int MAXN = 1010;
36 const int MAXM = 2000010;
37 const double eps = 1e-4;
38  
39 struct Node {
40     int l, r;
41     bool operator < (const Node& A) const {
42         return l < A.l;
43     }
44 }l[10000];
45 int n, m;
46  
47 int main()
48 {
49     //FIN;
50     while(cin >> n >> m) {
51         mem0(l);
52         rep (i, 0, m - 1) {
53             scanf("%d %d", &l[i].l, &l[i].r);
54         }
55         sort(l, l + m);
56         int ans = n + 1, maxr = l[0].r, curl = l[0].l;
57         rep (i, 1, m - 1) {
58             if(l[i].l > maxr) {
59                 ans += 2 * (maxr - curl);
60                 curl = l[i].l;
61                 maxr = l[i].r;
62             }
63             else maxr = max(l[i].r, maxr);
64         }
65         ans += 2 * (maxr - curl);
66         cout << ans << endl;
67     }
68     return 0;
69 }
View Code

D:CSU1539直接二分答案,通过V是可以算出是否可以通过每个杆的(这里还需要枚举反弹的次数,反正次数不多)。这里先贴上队友比赛时的代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <queue>
 5 #include <algorithm>
 6 #include <stack>
 7 #include <cmath>
 8 using namespace std;
 9 #define mem0(a) memset(a, 0, sizeof(a))
10  
11 const double eps = 1e-6;
12 const double maxans = 1e6;
13 const double pi = 3.14159265359;
14 double d, p[20], h[20];
15 int n, b;
16 double calc(double x, double vx, double vy) {
17     double a = -1.0 / 2 / vx / vx, b = vy / vx;
18     return a * x * x + b * x;
19 }
20 bool Check(double v, int total) {
21     double dd = d / total, sumd = 0, tt = dd / v / v;
22     if (tt >= 1) return 0;
23     double sita = asin(tt) / 2;
24     sita = max(sita, pi / 2 - sita);
25     double vx = v * cos(sita), vy = v * sin(sita);
26     int now = 0;
27     for (int i = 0; i < total; i++) {
28         while (p[now] > sumd && p[now] < sumd + dd) {
29             double x0 = p[now] - sumd;
30             if (calc(x0, vx, vy) < h[now]) return 0;
31             now++;
32         }
33         sumd += dd;
34     }
35     return 1;
36 }
37 double work(int total) {
38     double l = 0.000001, r = maxans;
39     while (fabs(r - l) > eps) {
40         double m = (l + r) / 2;
41         if (Check(m, total)) r = m;
42         else l = m;
43     }
44     return l;
45 }
46 bool Conflict(int t) {
47     for (int i = 0; i < t; i++) {
48         double tmp = d / (t + 1) * (i + 1);
49         for (int j = 0; j < n; j++) {
50             if (fabs(p[j] - tmp) < eps) return 1;
51         }
52     }
53     return 0;
54 }
55 int main()
56 {
57     //freopen("in.txt", "r", stdin);
58     while(cin >> d >> n >> b) {
59         for (int i = 0; i < n; i++) {
60             cin >> p[i] >> h[i];
61         }
62         double ans = maxans;
63         for (int i = 0; i <= b; i++) {
64             if (Conflict(i)) continue;
65             ans = min(ans, work(i + 1));
66         }
67         printf("%.5f
", ans);
68     }
69     return 0;
70 }
View Code

E:CSU1540赛后花了比较多的时间去A掉这道题,看懂题花了比较大的精力,A掉他花了更大的精力,这里就讲讲题目意思吧:

题目意思是说一辆车从起点开始随机到处乱走,现在知道的条件只有它从i - 1时刻到i时刻走了距离p,且i时刻GPS测出来的前进方向是d方向(E, W, N, S),问在最后的t时刻这辆车会停留在哪些位置。另外一个条件就是说若 k 时刻这辆车正在一个拐弯处,那么GPS测出来的时间可能是转弯前的方向,也有可能是转弯后的方向。

注意看数据范围  x , y <= 50  这时候我想你们知道该怎么做了= =(dfs+状态标记。。)

调试的我想死啊。。。

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf (-((LL)1<<40))
 17 #define lson k<<1, L, mid
 18 #define rson k<<1|1, mid+1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FIN freopen("in.txt", "r", stdin)
 23 #define FOUT freopen("out.txt", "w", stdout)
 24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
 25  
 26 template<class T> int CMP_MIN(T a, T b) { return a < b; }
 27 template<class T> int CMP_MAX(T a, T b) { return a > b; }
 28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 32  
 33 //typedef __int64 LL;
 34 typedef long long LL;
 35 const int MAXN = 1010;
 36 const int MAXM = 20010;
 37 const double eps = 1e-4;
 38  
 39 const int dx[4] = {0, -1, 0, 1};
 40 const int dy[4] = {1, 0, -1, 0};
 41 char pas[5] = {"NWSE"};
 42 int DN = 0, DS = 2, DE = 3, DW = 1;
 43  
 44 struct Point {
 45     int x, y, d;
 46     Point(){}
 47     Point(int _x, int _y, int _d){
 48         x = _x; y = _y, d = _d;
 49     }
 50     bool operator < (Point& A) const {
 51         return x != A.x ? x < A.x : y < A.y;
 52     }
 53 }st, q[2][3000];
 54 struct Line {
 55     Point u, v;
 56 }v[100], h[100], tmp;
 57 int cnt[2], n, t, vcnt, hcnt, e[60][60][5];
 58 bool vis[55][55][4][20];
 59  
 60 void addEdge() {
 61     mem0(e);
 62     rep (i, 0, vcnt - 1) rep (j, 0, hcnt - 1) {
 63         if(h[j].u.y < v[i].u.y || h[j].u.y > v[i].v.y
 64             || v[i].u.x < h[j].u.x || v[i].u.x > h[j].v.x) continue;
 65         int fo[4] = {0};
 66         if(v[i].v.y == h[j].u.y) fo[0] = 1;
 67         if(v[i].u.x == h[j].u.x) fo[1] = 1;
 68         if(v[i].u.y == h[j].u.y) fo[2] = 1;
 69         if(v[i].u.x == h[j].v.x) fo[3] = 1;
 70         rep (k, 0, 3) if(!fo[k]) {
 71             e[v[i].u.x][h[j].u.y][k] = 1;
 72         }
 73     }
 74     rep (i, 0, vcnt - 1) {
 75         int curx = v[i].u.x, miny = v[i].u.y, maxy = v[i].v.y;
 76         rep (j, miny, maxy) {
 77             if(j < maxy) e[curx][j][DN] = 1;
 78             if(j > miny) e[curx][j][DS] = 1;
 79         }
 80     }
 81     rep (i, 0, hcnt - 1) {
 82         int minx = h[i].u.x, maxx = h[i].v.x, cury = h[i].u.y;
 83         rep (j, minx, maxx) {
 84             if(j < maxx) e[j][cury][DE] = 1;
 85             if(j > minx) e[j][cury][DW] = 1;
 86         }
 87     }
 88 }
 89  
 90 int check(int x, int y, int od, int d, int s)
 91 {
 92     int isN = e[x][y][DN], isS = e[x][y][DS], isE = e[x][y][DE], isW = e[x][y][DW];
 93     int sum = isN + isS + isW + isE;
 94     if(sum == 4) {
 95         if(od == s) return d != (s + 2) % 4;
 96         return d == s;
 97     }
 98     if(sum == 3){
 99         return s != od ? d == s : 1;
100     }
101     if(sum == 2) {
102         if(isN&&isS || isE&&isW) return s == d && d == od;
103         int a = isN ? DN : DS, b = isE ? DE : DW;
104         if((a + 2) % 4 == od) return (s == od || s == b) && d == b;
105         if((b + 2) % 4 == od) return (s == od || s == a) && d == a;
106     }
107     return 1;
108 }
109  
110 void dfs(int x, int y, int odir, int dir, int seems, int now, int s)
111 {
112     if(s == 0) {
113         if(check(x, y, odir, dir, seems)) {
114             q[now][cnt[now]++] = Point(x, y, dir);
115         }
116         return ;
117     }
118     if(vis[x][y][dir][s]) return ;
119     vis[x][y][dir][s] = 1;
120     x += dx[dir]; y += dy[dir];
121     rep (i, 0, 3) if(e[x][y][i] && (i + 2) % 4 != dir) {
122         dfs(x, y, dir, i, seems, now, s - 1);
123     }
124 }
125  
126 int conv(char ch) {
127     if(ch == 'N') return DN;
128     if(ch == 'S') return DS;
129     if(ch == 'E') return DE;
130     return DW;
131 }
132  
133 int cmp(Point a, Point b) {
134     return a < b;
135 }
136  
137 int main()
138 {
139  
140     while(~scanf("%d %d %d %d", &n, &st.x, &st.y, &t)) {
141         vcnt = hcnt = 0;
142         mem0(cnt);
143         rep (i, 0, n - 1) {
144             scanf("%d %d %d %d", &tmp.u.x, &tmp.u.y, &tmp.v.x, &tmp.v.y);
145             if(tmp.u.x > tmp.v.x) swap(tmp.u.x, tmp.v.x);
146             if(tmp.u. y > tmp.v.y) swap(tmp.u.y, tmp.v.y);
147             if(tmp.u.x == tmp.v.x) v[vcnt++] = tmp;
148             else h[hcnt++] = tmp;
149             //printf("%d %d %d %d
", tmp.u.x, tmp.u.y, tmp.v.x, tmp.v.y);
150         }
151         addEdge();
152         int now = 0, step = 0; char dir;
153         rep (i, 0, 3) if(e[st.x][st.y][i]) {
154             q[now][cnt[now]++] = Point(st.x, st.y, i);
155         }
156         rep (i, 0, t - 1) {
157             scanf("%d %c", &step, &dir);
158             now = !now; mem0(vis); cnt[now] = 0;
159             rep (j, 0, cnt[!now] - 1) {
160                 dfs(q[!now][j].x, q[!now][j].y, -1, q[!now][j].d, conv(dir), now, step);
161             }
162         }
163         sort(q[now], q[now] + cnt[now], cmp);
164         int lax = -1, lay = -1;
165         rep (i, 0, cnt[now] - 1) if(q[now][i].x != lax || q[now][i].y != lay) {
166             printf("%d %d
", q[now][i].x, q[now][i].y);
167             lax = q[now][i].x;
168             lay = q[now][i].y;
169         }
170     }
171     return 0;
172 }
View Code

F:CSU1541题目大意就是给一个图,问为了构建最先生成树,哪些边是不可被替代的,(不可被替代就是说如果这条边被删除,最小生成树的权值会变大)

上面已经说了如果被删除权值会变大就是不可替代的,所以先求一遍最小生成树,然后枚举最小生成树的边,删除看最小生成树权值是否变大,或图是否还连通,这样复杂度就是O(m * logm) + O(m * n),正好可以过

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <vector>
 8 #include <cstdio>
 9 #include <cctype>
10 #include <cstring>
11 #include <cstdlib>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 #define INF 0x3f3f3f3f
16 #define inf (-((LL)1<<40))
17 #define lson k<<1, L, mid
18 #define rson k<<1|1, mid+1, R
19 #define mem0(a) memset(a,0,sizeof(a))
20 #define mem1(a) memset(a,-1,sizeof(a))
21 #define mem(a, b) memset(a, b, sizeof(a))
22 #define FIN freopen("in.txt", "r", stdin)
23 #define FOUT freopen("out.txt", "w", stdout)
24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
25  
26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
32  
33 //typedef __int64 LL;
34 typedef long long LL;
35 const int MAXN = 1010;
36 const int MAXM = 2000010;
37 const double eps = 1e-4;
38  
39 struct Edge {
40     int u, v, w;
41     bool operator < (const Edge& A) const {
42         return w < A.w;
43     }
44 }e[51000];
45  
46 int minE[51000], cnt, fa[510], n, m;
47  
48 int findP(int x) { return x == fa[x] ? x : fa[x] = findP(fa[x]); }
49  
50 int kruskal(int forbidon) {
51     int ret = 0, num = n - 1;
52     rep (i, 0, n) fa[i] = i;
53     rep (i, 0, m - 1) if(i != forbidon) {
54         int x = findP(e[i].u), y = findP(e[i].v);
55         if(x != y) {
56             ret += e[i].w;
57             fa[x] = y;
58             if(forbidon < 0) minE[cnt++] = i;
59             num --;
60         }
61     }
62     return ret = num ? INF : ret;
63 }
64  
65 int main()
66 {
67     //FIN;
68     while(cin >> n >> m) {
69         rep (i, 0, m - 1) scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].w);
70         sort(e, e + m);
71         cnt  = 0;
72         int minW = kruskal(-1);
73         int num = 0, sum = 0;
74         rep (i, 0, cnt - 1) {
75             if(kruskal(minE[i]) > minW) num ++, sum += e[minE[i]].w;
76         }
77         cout << num << " " << sum << endl;
78     }
79     return 0;
80 }
View Code

G:题目是说一个原始匹配的括号序列,每次将位置p的括号反转,问最左侧需要将哪个括号反转使得括号序列重新获得匹配。

结题报告:http://www.cnblogs.com/gj-Acit/p/4361520.html

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf (-((LL)1<<40))
 17 #define lson k<<1, L, mid
 18 #define rson k<<1|1, mid+1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FIN freopen("in.txt", "r", stdin)
 23 #define FOUT freopen("out.txt", "w", stdout)
 24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
 25 
 26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
 27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
 28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 32 
 33 //typedef __int64 LL;
 34 typedef long long LL;
 35 const int MAXN = 1010;
 36 const int MAXM = 20010;
 37 const double eps = 1e-4;
 38 
 39 int n, q, p, len;
 40 char s[310000]={"1"};
 41 struct Node {
 42     int f, a, s;
 43 }t[310000<<2];
 44 
 45 char rev(char c) { return (c == '(') ? ')' : '('; }
 46 
 47 void buildTree(int k, int L, int R, int p, int a)
 48 {
 49     t[k].s = 0;
 50     if(L == R) {
 51         t[k].f = a - L; t[k].a = a;
 52         return ;
 53     }
 54     int mid = (L + R) >> 1;
 55     if(p > mid) buildTree(rson, p, a);
 56     else buildTree(lson, p, a);
 57     t[k].f = min(t[k<<1].f, t[k<<1|1].f);
 58     t[k].a = min(t[k<<1].a, t[k<<1|1].a);
 59 }
 60 
 61 void init()
 62 {
 63     mem0(t);
 64     int sum = 0;
 65     len = strlen(s) - 1;
 66     rep (i, 1, len) {
 67         sum += (s[i] == '(') ? 1 : -1;
 68         buildTree(1, 1, len, i, sum);//建树
 69     }
 70 }
 71 
 72 //向下传延时标记
 73 void pushDown(int k)
 74 {
 75     t[k<<1].s += t[k].s; t[k<<1].a += t[k].s; t[k<<1].f += t[k].s;
 76     t[k<<1|1].s += t[k].s; t[k<<1|1].a += t[k].s; t[k<<1|1].f += t[k].s;
 77     t[k].s = 0;
 78 }
 79 
 80 //更新操作,将区间[p, len]的所有值都+val
 81 void update(int k, int L, int R, int p, int val)
 82 {
 83     if(p <= L) {
 84         t[k].s += val;
 85         t[k].a += val;
 86         t[k].f += val;
 87         return ;
 88     }
 89     pushDown(k);
 90     int mid = (L + R) >> 1;
 91     if(p <= mid) update(lson, p, val);//左侧可能需要更新
 92     update(rson, p, val);//右侧是一定要更新的,因为需要更新的区间为[p, len]
 93     t[k].f = min(t[k<<1].f, t[k<<1|1].f);
 94     t[k].a = min(t[k<<1].a, t[k<<1|1].a);
 95 }
 96 
 97 //查询最左侧的右括号
 98 int query1(int k, int L, int R)
 99 {
100     if(L == R) return L;
101     int mid = (L + R) >> 1;
102     pushDown(k);
103     if(t[k<<1].f < 0) return query1(lson);
104     return query1(rson);
105 }
106 
107 //查询从len往前连续的最长的满足a>=2的点,也就是最后一个<2的位置+1
108 int query2(int k, int L, int R)
109 {
110     if(L == R) return min(len, L + 1);
111     int mid = (L + R) >> 1;
112     pushDown(k);
113     if(t[k<<1|1].a < 2) return query2(rson);
114     return query2(lson);
115 }
116 
117 int main()
118 {
119     //FIN;
120     while(~scanf("%d %d%*c %s", &n, &q, s + 1)) {
121         init();
122         rep (i, 0, q - 1) {
123             scanf("%d", &p);
124             s[p] = rev(s[p]); update(1, 1, len, p, s[p] == ')' ? -2 : 2);
125             if(s[p] == ')') p = query1(1, 1, len);//find first )
126             else p = query2(1, 1, len); //find last < 2
127             s[p] = rev(s[p]); update(1, 1, len, p, s[p] == ')' ? -2 : 2);
128             printf("%d
", p);
129         }
130     }
131     return 0;
132 }
View Code
原文地址:https://www.cnblogs.com/gj-Acit/p/4375075.html