个相互独立的非连通区域,对于某一连通区域
所以答案是
话外提一句,统计一个图的边的数量和点的总数可以在q.pop()
时就做标记统计,这样可以统计不同要求的点的各个数量。本题对于点的统计采用的是后者。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m;
int n0,m0;
vector<int> connects[200001];
bool visited[200001];
int color[2];
int res[200001];
typedef pair<int, int> p;
set<p>s;
vector<p> ans;
void bfs(int i)
{
s.clear();
queue<int> q;
q.push(i);
bool tag=0;
while(!q.empty())
{
int top=q.front();
q.pop();
if(visited[top])continue;
visited[top]=true;
color[res[top]]++;
for(int i=0;i<connects[top].size();i++)
{
int next=connects[top][i];
if(next<=top)s.insert({next,top});
else s.insert({top,next});
if(!visited[next])
{
res[next]=(res[top]+1)%2;
q.push(next);
}
else
{
if(res[next]==res[top])tag=1,cout<<"0"<<endl,exit(0);
}
}
}
if(tag)color[0]=color[1]=0;
else m0+=s.size();
return;
}
signed main()
{
cin >> n >> m;
for (int i = 1, u, v; i <= m; i++)
{
cin >> u >> v;
connects[u].push_back(v);
connects[v].push_back(u);
}
for (int i = 1; i <= n; i++)
{
if (visited[i])continue;
memset(color,0,sizeof(color));
bfs(i);
n0+=(color[0]+color[1]);
ans.push_back({color[0], color[1]});
}
int answ=0;
for(int i=0;i<ans.size();i++)
{
answ+=(ans[i].first*ans[i].second)+(ans[i].first+ans[i].second)*(n0-(ans[i].first+ans[i].second));
n0-=ans[i].first+ans[i].second;
}
cout<<answ-m0<<endl;
system("pause");
return 0;
}
题目大意:
一共有
着实没想到这竟然是一个生成树的题,果然现在我的脑子已经魔怔了,看见最值和选择就是
不过仔细考虑,确实也是挺巧的。
每两个球都确定唯一对应的得分,是一个
而且,这个题没有出现说相互独立的
father[getfather(p)]=getfather(q)
,或者写作father[father[p]]=father[q]
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef struct node
{
pair<int, int> uv;
int w;
bool operator<(const node &x) const
{
return x.w > w;
}
} node;
#define maxn int(1e7)
int a[501];
int father[501];
int n, m;
void init()
{
for (int i = 1; i <= n; i++)
{
father[i] = i;
}
}
int getfather(int x)
{
if (x == father[x])
return x;
else
return getfather(father[x]);
}
#define mod m
int quickpow(int a, int n)
{
int e = 1;
while (n)
{
if (n & 1)
(e *= a) %= mod;
(a *= a) %= mod;
n >>= 1;
}
return e;
}
int calc(int i, int j)
{
return (quickpow(a[i], a[j]) % mod + quickpow(a[j], a[i]) % mod) % mod;
}
bool visited[501];
int kruskal(priority_queue<node> q)
{
int ans = 0;
while (!q.empty())
{
node x = q.top();
q.pop();
if(getfather(x.uv.first)!=getfather(x.uv.second))
{
father[getfather(x.uv.first)]=getfather(x.uv.second);
ans+=x.w;
}
}
return ans;
}
signed main()
{
cin >> n >> m;
init();
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
priority_queue<node> q;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
{
q.push((node{pair<int, int>(i, j), calc(i, j)}));
}
cout<<kruskal(q)<<endl;
system("pause");
return 0;
}
题目大意:
本题要求在线,根据
首先,给出一个正整数
然后,给出一个正整数
对于本题来说,只需要划分ST区域,因为这样划分可以保证任意两端能组成一个满足要求的并集。划分好之后,对于每一次询问,输出两端的两条线段序号就可以了。
构建时ST不需要存放区间最大或最小值信息,只需要存放线段的编号。
因为单点不成线段,所以不从0开始画。
#include <bits/stdc++.h>
using namespace std;
int f[4001][21];
int cnt = 0;
int main()
{
ios::sync_with_stdio(false);
int n;
cin >> n;
for (int i = 0; i <= 20; i++)
{
for (int j = 1; j + (1 << i) - 1 <= n; j++)
{
f[j][i] = ++cnt;
}
}
cout << cnt << endl;
for (int i = 0; i <= 20; i++)
{
for (int j = 1; j + (1 << i) - 1 <= n; j++)
{
cout << j << " " << j + (1 << i) - 1 << endl;
}
}
int q;
cin >> q;
while (q--)
{
int l, r;
cin >> l >> r;
int k = log2(r - l + 1);
cout << f[l][k] << ' ' << f[r - (1 << k) + 1][k] << endl;
}
}
请我喝杯咖啡吧~