好了我活了
这么长时间不写题就是会变菜啊
这种题写这么长时间QAQ
这个题刚看到的时候一脸mb
然后看到数据范围就放心了
就写了个子集枚举就交上去了
但是要注意的是最后统计答案的时候,是每个数字出现的次数两两相乘再求和
#include
#include
#include
#include
using namespace std;
const int MAXN = 10000 + 5;
int n,m,k;
int all[MAXN];
bool solve(int jh) {
//TODO: init
int tmp[MAXN] = {0};
for(int i = 0;i < n;i ++) {
tmp[i] = all[i];
}
//TODO: make tmp by jh
for(int t = 0;t < m;t ++) {
if((jh >> t) & 1)
continue;
for(int i = 0;i < n;i ++)
tmp[i] |= (1 << t);
}
//TODO: unique
sort(tmp, tmp + n);
int l = 0,r = 0;
int tot = 0;
while(true) {
while(tmp[l] == tmp[r])
r ++;
if(r > n)
break;
tmp[tot ++] = r - l;
l = r;
}
//TODO: get ans
int ans = 0;
for(int i = 0;i < tot;i ++)
for(int j = i + 1;j < tot;j ++)
ans += tmp[i] * tmp[j];
return ans >= k;
}
int solve() {
int ans = 0;
for(int i = 0;i < (1 << m);i ++) {
ans += solve(i);
}
return ans;
}
int T;
int main() {
scanf("%d", &T);
for(int t = 1;t <= T;t ++) {
memset(all, 0, sizeof(all));
scanf("%d %d %d",&n, &m, &k);
for(int i = 0;i < n;i ++) {
for(int j = 0;j < m;j ++) {
char t = getchar();
while(!isalpha(t))
t = getchar();
if(t == 'A')
all[i] |= (1 << j);
}
}
printf("Case #%d: %d\n", t,solve());
}
}
emmmm T2还是有点坑的吧,要注意到字典序最小的当然就是一个字母啦!
然后就是26个前缀和,还挺好写的
#include
#include
#include
#include
using namespace std;
const int MAXN = 100000 + 5;
int T;
int sum[26][MAXN];
int n,q;
char c[MAXN];
int main()
{
scanf("%d",&T);
for(int t = 1;t <= T; t ++)
{
printf("Case #%d:\n",t);
scanf("%d %d",&n,&q);
memset(sum,0,sizeof(sum));
for(int i = 1;i <= n;i ++)
{
c[i] = getchar();
while(!isalpha(c[i]))
c[i] = getchar();
}
for(int i = 1;i <= n;i ++)
sum[c[i] - 'A'][i] ++;
for(int j = 0;j < 26;j ++)
for(int i = 1;i <= n;i ++)
sum[j][i] += sum[j][i - 1];
int a,b;
while(q --)
{
scanf("%d %d",&a,&b);
for(int i = 0;i < 26;i ++)
if(sum[i][b] - sum[i][a - 1])
{
printf("%d\n", sum[i][b] - sum[i][a - 1]);
break;
}
}
}
return 0;
}
这是个二分图匹配?或者说网络流?
不知道,不会做
等题解吧……
【我一定好好学网络流
弃疗
破题能做?
签到题吧……
我是跑了两遍克鲁斯卡尔
然后傻傻的吧红色和蓝色给交换掉
【这套题是告诉我们题目难度与顺序无关吗233333
#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 100000 + 5;
int n,m;
struct edge
{
int f,t,v;
char c;
bool operator < (const edge &b)const
{
return v < b.v;
}
}e[MAXN];
struct bcj
{
int fa[MAXN];
void init()
{
for(int i = 1;i <= n;i ++)
fa[i] = i;
return;
}
int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool same(int x,int y)
{
return find(x) == find(y);
}
void merge(int x,int y)
{
x = find(x);
y = find(y);
fa[x] = y;
return;
}
}b;
int ans[MAXN],tmp[MAXN];
queue <int> q;
int kru()
{
int tot = 0,count = 0;
sort(e + 1, e + m + 1);
b.init();
while(!q.empty())
q.pop();
for(int i = 1;i <= m;i ++)
{
if(e[i].c != 'B' && !b.same(e[i].f, e[i].t))
{
tot += e[i].v;
count ++;
b.merge(e[i].f, e[i].t);
}
else
q.push(e[i].v);
}
return count == n - 1 ? tot : -1;
}
void tj()
{
int t = kru();
if(t == -1)
{
for(int i = 1;i <= m;i ++)
ans[i] = -1;
return;
}
for(int i = 1;i < n - 1;i ++)
ans[i] = -1;
ans[n - 1] = t;
for(int i = n;i <= m;i ++)
{
ans[i] = ans[i - 1] + q.front();
q.pop();
}
return;
}
void change(int x)
{
switch (e[x].c)
{
case 'B':e[x].c = 'R';break;
case 'R':e[x].c = 'B';break;
default:break;
}
return;
}
int really(int i)
{
if(ans[i] == -1)
return tmp[i];
if(tmp[i] == -1)
return ans[i];
return min(ans[i],tmp[i]);
}
int T;
int main()
{
scanf("%d",&T);
for(int t = 1;t <= T;t ++)
{
printf("Case #%d:\n",t);
scanf("%d %d",&n,&m);
memset(tmp,0,sizeof(tmp));
memset(ans,0,sizeof(ans));
for(int i = 1;i <= m;i ++)
scanf("%d %d %d %c",&e[i].f, &e[i].t, &e[i].v, &e[i].c);
tj();
for(int i = 1;i <= m;i ++)
change(i);
for(int i = 1;i <= m;i ++)
tmp[i] = ans[i];
tj();
for(int i = 1;i <= m;i ++)
ans[i] = really(i);
for(int i = 1;i <= m;i ++)
printf("%d\n",ans[i]);
}
return 0;
}