码迷,mamicode.com
首页 > 其他好文 > 详细

经典傻逼题

时间:2019-12-14 23:08:40      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:电脑   max   define   格式   正整数   修改   highlight   memset   ++i   

技术图片

Description

这是一道经典傻逼题,对经典题很熟悉的人也不要激动,希望大家不要傻逼。
考虑一张N个点的带权无向图,点的编号为1到N。 对于图中的任意一个点集(可以为空或者全集),所有恰好有一个端点在这个点集中的边组成的集合被称为割。 一个割的权值被定义为所有在这个割上的边的异或和。

一开始这张图是空图,现在,考虑给这张无向图不断的加边,加入每条边之后,你都要求出当前权值最大的割的权值, 注意加入的边永远都不会消失。

Input

输入的第一行包括一个数ID表示数据编号, 如第一组数据中的ID = 1。注意样例数据中的ID = 0。
接下来的第一行包括两个整数N,M表示图的点数和总共加的边。
接下来M行,每行三个正整数x,y,w表示在点x和点y之间加入一条权值为w的边。
注意x和y可能相同,两条不同的边也可能连接了同一对点。

此外, w将以二进制形式从高位向低位给出,比如, 6 = 110(2),因此如果边
权为 6,那么w将会是110。
$1leq Nleq 500,1 leq M leq 1000$, $0 leq L leq 1000$, $1 leq x,y leq N$

Output

输出M行,按顺序输出每一条边加入之后权值最大的割的权值。
同样,你也要以二进制形式输出,形式和输入格式中描述的形式一样。

Sample Input

1
2
3
4
5
6
7
8
0 3
6
1 2 1
1 2 1
3 3 111
1 3 101101
1 2 1011
2 3 111011

Sample Output

1
2
3
4
1 0 0
101101
101101
110000

HINT

前三条边加入之后的答案较为显然,考虑后三条边,加入第六条边之前, 考

虑点集${1,2}$,它对应的割只有第四条边, 因此答案就是第四条边的权值,考虑加

入最后一条边以后的情况,此时点集${1,2}$对应的割变成了第四条边和第六条边组

成的集合,权值也发生了相应的改变。 点集${2}$对应的割是第五条边和第六条边

组成的集合, 可以证明这就是权值最大的割,权值为$1011(2)$xor$111011(2) =110000(2)$

技术图片

Solution

考虑这个”割”的限制貌似并不是很好做,把边放到点上,每次选出一些点集。对于一条边,如果一条边的两个端点都在选出的点集中,那么在异或中就会被抵消掉,相当于没有选。每次选择一个点,相当于选择了和它相连的所有边,这个点的权值就是和它相接的所有边的异或和。

那么问题变成了每次选择一个点集,每个点有一个权值,使得选出的点的异或和做大。

这样是一个裸的线性基模板题。但是每次暴力去跑复杂度为$O(mnl^2)$显然不对。

然后那个异或可以bitset搞一下就是$O(frac{mnl^2}{w})$,这样电脑跑的快就可以过了

比较好理解的是一个线段树分治的离线做法。对于每个点的固定的一个权值,存在于图中的时间是一个连续的区间,对于$m$次修改,可以把这个权值打到线段树上面对应的$log$个节点上去,但这个时候并不下传,具体来说就是线段树上的每一个节点开一个std::vector存一下这个区间上的所有。

那么现在线段树上每个点维护的是一个区间的bitset的集合,我们想知道答案就最后在线段树上dfs一下,访问每一个点的时候加入当前dfs的基中,到叶子节点的时候在基中取max就是答案。

正解很短但是比较神仙,傻逼不太会,先坑着。

PS: 由于本傻逼考场上没想到有bitset这个东西结果还手打了一个二进制高精度。(傻逼不仅啥都不会傻逼题就更不会了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

using namespace std;
#define IL inline
IL int () {
char ch = getchar(); int u = 0, f = 1;
while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) { u = (u << 1) + (u << 3) + ch - 48; ch = getchar(); }
return u * f;
}
IL int read2() {
char ch = getchar(); int u = 0, f = 1;
while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) { u = (u << 1) + ch - 48; ch = getchar(); }
return u * f;
}
#define rep(i, j, k) for (int i = j; i <= k; ++i)
#define repd(i, j, k) for (int i = j; i >= k; --i)

typedef long long ll;

const int maxn = 1e5 + 10;
int val[maxn], n, m, id, vis[maxn];
int L;

namespace BF {
namespace subtask2 {
class my2 {
public:
unsigned long long len[16]; int cd;
my2() { memset(len, 0, sizeof len); cd = 0; }
void init (char *a, int n) {
cd = (n - 1) / 64;
rep(i, 0, n - 1) len[(n - i - 1) / 64] |= (unsigned long long)(a[i] - '0') << ((n - i - 1) & 63);
}
void operator = (const my2 rhs) { memcpy(len,rhs.len,sizeof len); cd = rhs.cd; }
void operator = (int x) {
memset(len, 0, sizeof (len));
cd = 0;
}
bool operator < (const my2 rhs) {
if (cd != rhs.cd) return cd < rhs.cd;
repd(i, cd, 0) if (len[i] != rhs.len[i]) return len[i] < rhs.len[i];
return false;
}
my2 operator ^ (const my2 rhs) const {
my2 rtn;
rtn.cd = max(cd, rhs.cd);
rep(i, 0, rtn.cd) rtn.len[i] = len[i] ^ rhs.len[i];
while (rtn.cd && rtn.len[rtn.cd] == 0) rtn.cd--;
return rtn;
}
void Xor (const my2 rhs) {
cd = max(cd, rhs.cd);
rep(i, 0, cd) len[i] = len[i] ^ rhs.len[i];
while (cd && len[cd] == 0) cd--;
}
void p32(unsigned long long x,bool f1) {
int b=1;
repd(i, 63, 0) if(x&(1ull<<i))putchar 大专栏  经典傻逼题('1'),f1=1; else if(f1)putchar('0');
}
void print() {
if (cd == 0 && len[0] == 0) { puts("0"); return; }
repd(i, cd, 0) p32(len[i],(i!=cd));
printf("n");
}
void update(const my2 rhs) {
int nw=max(cd,rhs.cd);
repd(i, nw, 0) if(len[i]&&rhs.len[i]) return;
else if(!len[i]&&rhs.len[i]) break;
cd=max(cd,rhs.cd);
repd(i,cd,0) len[i]=len[i]^rhs.len[i];
}
}val[505];
namespace LineBase {
my2 a[1005];
int main(my2 *b, int n) {
rep(i, 0, min(L * 64,1000)) a[i] = 0;
rep (i, 1, n) {
if(!b[i].cd&&b[i].len[0]==0)continue;
my2 tmp = b[i];
repd (j, tmp.cd, 0) {
repd(bi, 63, 0) {
if (tmp.len[j]>>bi&1ull) {
if (a[(j<<6)|bi].cd == 0 && a[(j<<6)|bi].len[0] == 0) a[(j<<6)|bi] = tmp;
tmp.Xor(a[(j<<6)|bi]);
}
}
}
}
my2 ans; ans = 0;
repd (j, min(L * 64,1000), 0) {
if (ans < (ans ^ a[j])) ans.Xor(a[j]);
} ans.print();
return 0;
}
int ins(int i,int P) {
my2 tmp = val[i];
repd (j, tmp.cd, 0) {
repd(bi, 63, 0) {
if (tmp.len[j]>>bi&1ull) {
if (a[(j<<6)|bi].cd == 0 && a[(j<<6)|bi].len[0] == 0) a[(j<<6)|bi] = tmp;
tmp.Xor(a[(j<<6)|bi]);
}
}
}
my2 ans; ans = 0;
repd (j, min(L * 64,1000), 0) {
if (ans < (ans ^ a[j])) ans.Xor(a[j]);

} if(P) ans.print();
}
}
char temp[1005];
IL void work() {
rep(i, 1, m) {
int x = read(), y = read();
scanf("%s", temp); int lent = strlen(temp);
my2 qwq;
qwq.init(temp, lent);
val[x].Xor(qwq);
val[y].Xor(qwq);
// cerr<<"---n";
// val[x].print(); val[y].print();
if (id != 4 && id != 5) LineBase::main(val, n);
else LineBase::ins(x,0),LineBase::ins(y,1);
}
}
}
}

namespace SEG {
const int maxn = 1005;
class my2 {
public:
unsigned long long len[16]; int cd;
my2() { memset(len, 0, sizeof len); cd = 0; }
void init (char *a, int n) {
cd = (n - 1) / 64;
rep(i, 0, n - 1) len[(n - i - 1) / 64] |= (unsigned long long)(a[i] - '0') << ((n - i - 1) & 63);
}
void operator = (const my2 rhs) { memcpy(len,rhs.len,sizeof len); cd = rhs.cd; }
void operator = (int x) {
memset(len, 0, sizeof (len));
cd = 0;
}
bool operator < (const my2 rhs) {
if (cd != rhs.cd) return cd < rhs.cd;
repd(i, cd, 0) if (len[i] != rhs.len[i]) return len[i] < rhs.len[i];
return false;
}
my2 operator ^ (const my2 rhs) const {
my2 rtn;
rtn.cd = max(cd, rhs.cd);
rep(i, 0, rtn.cd) rtn.len[i] = len[i] ^ rhs.len[i];
while (rtn.cd && rtn.len[rtn.cd] == 0) rtn.cd--;
return rtn;
}
void Xor (const my2 rhs) {
cd = max(cd, rhs.cd);
rep(i, 0, cd) len[i] = len[i] ^ rhs.len[i];
while (cd && len[cd] == 0) cd--;
}
void p64(unsigned long long x,bool f1) {
int b=1;
repd(i, 63, 0) if(x&(1ull<<i))putchar('1'),f1=1; else if(f1)putchar('0');
}
void print() {
if (cd == 0 && len[0] == 0) { puts("0"); return; }
repd(i, cd, 0) p64(len[i],(i!=cd));
printf("n");
}
IL bool count() { return (cd || len[0]); }
void update(const my2 rhs) {
int nw=max(cd,rhs.cd);
repd(i, nw, 0) if(len[i]&&rhs.len[i]) return;
else if(!len[i]&&rhs.len[i]) break;
cd=max(cd,rhs.cd);
repd(i,cd,0) len[i]=len[i]^rhs.len[i];
}
}val[505];
class Lb {
public:
my2 a[1005];
void push_back(my2 inx) {
repd (j, inx.cd, 0) {
repd(bi, 63, 0) {
if (inx.len[j]>>bi&1ull) {
if (a[(j<<6)|bi].cd == 0 && a[(j<<6)|bi].len[0] == 0) a[(j<<6)|bi] = inx;
inx.Xor(a[(j<<6)|bi]);
}
}
}
}
my2 queryMax() {
my2 ans; ans = 0;
repd (j, min(1000,L*64), 0) if (ans < (ans ^ a[j])) ans.Xor(a[j]);
return ans;
}
};

vector<my2>sgt[maxn << 2];
char s[maxn]; int lst[maxn];
#define ls (p << 1)
#define rs (p << 1 | 1)
void modify(int p, int x, int y, int l, int r, my2 qwq) {
if (x == l && y == r) {
sgt[p].push_back(qwq);
return;
} int mid = (x + y) >> 1;
if (r <= mid) modify(ls, x, mid, l, r, qwq);
else if (l > mid) modify(rs, mid + 1, y, l, r, qwq);
else modify(ls, x, mid, l, mid, qwq), modify(rs, mid + 1, y, mid + 1, r, qwq);
}
void dfs(int p, Lb &cur, int x, int y) {
Lb temp = cur;
for (int i = 0; i < sgt[p].size(); ++i) {
temp.push_back(sgt[p][i]);
}
if (x == y) temp.queryMax().print();
else dfs(ls, temp, x, (x + y) >> 1), dfs(rs, temp, ((x + y) >> 1) + 1, y);
}
IL void work() {
rep(i, 1, m) {
int x = read(), y = read();
scanf("%s", s);
my2 qwq;
qwq.init(s, strlen(s));
if (lst[x]) modify(1, 1, m, lst[x], i - 1, val[x]);
if (lst[y]) modify(1, 1, m, lst[y], i - 1, val[y]);
val[y].Xor(qwq); val[x].Xor(qwq);
lst[x] = lst[y] = i;
}
rep(i, 1, n) if (lst[i]) { modify(1, 1, m, lst[i], m, val[i]); }
Lb temp;
dfs(1, temp, 1, m);
}
}

int Lp[20] = {1000, 32, 32, 100, 1000, 1000, 300, 300, 1000, 1000, 1000};
int main() {
// freopen("shabiti.in", "r", stdin);
// freopen("shabiti.out", "w", stdout);
id = read();
L = Lp[id] + 3; L /= 64; L++;
n = read(), m = read();
//BF::subtask2::work();
SEG::work();
return 0;
}

经典傻逼题

标签:电脑   max   define   格式   正整数   修改   highlight   memset   ++i   

原文地址:https://www.cnblogs.com/lijianming180/p/12041180.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!