[大战div2D]Codeforces Round #816 (Div. 2) D. 2+ doors
碎碎念
看到CF已经有会打算法竞赛的AI了,不知道是不是我火星- -,据说水平约等于rating1300,知乎说“大概是一个初学OI三个月的小学生水平”
笨人去看了看自己的分数,第一次到达1300正好在初学ACM的第三个月,原来我是小学生啊(大喜
于是决定摆脱小学生称号早日上篮,开始大战cf的2D
但是马上要网络赛+四级+数学建模了也没多少时间(悲
题意: 给定\(n\)个未知数的数组\(a\)和\(q\)个陈述\((i,j,x)\),表示\(a[i]\ |\ a[j]=x\),求出满足这\(q\)个陈述的最小字典序的\(a\)数组。
数据范围: $q (1≤n≤10^5, 0≤q≤2⋅10^5),(1≤i,j≤n, 0≤x<2^{30}) $
分析:由于二进制不进位,可以把每个数都拆分成二进制位来进行判断。将\(a\)的每一个数字都初始化为\(1<<30-1\),设\(a[i](k)\)表示\(a\)数组第\(i\)个数字的第\(k\)位,如果\(x(k)=0\),则直接将\(a[i](k)、a[j](k)\)置为\(0\)。如果\(x(k)=1\),则在\(a[i](k),a[j](k)\)之间连边,点权即为\(a[i](k),a[j](k)\)。对于每一个有边的点权为\(1\)的点\(p\),遍历与它有边的点\(q\),如果存在\(q=0\),则\(p\)不能为\(0\),否则\(p\)可以为\(0\)。
特判:当\(i=j\)时a[i]=x,否则会wa80
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
const int N=2e5+100;
int t,n,q,ans[N];
bool st[N];
vector<pair<int,int> > v[N];
void solve()
{
cin>>n>>q;
for(int i=1;i<=n;i++) ans[i]=(1<<30)-1;
for(int i=1;i<=q;i++)
{
int a,b,c;cin>>a>>b>>c;
if(a==b)
{
st[a]=1;
ans[a]=c;
}
else
{
v[a].push_back({b,c});
v[b].push_back({a,c});
for(int j=0;j<=29;j++)
{
if((c>>j&1)==0)
{
if(ans[a]>>j&1)ans[a]-=(1<<j);
if(ans[b]>>j&1)ans[b]-=(1<<j);
}
}
}
}
for(int j=0;j<=29;j++)
{
for(int i=1;i<=n;i++)
{
if(st[i]) continue;
if((ans[i]>>j&1)==0) continue;
bool flag=1;
for(auto p:v[i])
{
int k=p.first,x=p.second;
if((x>>j&1)==0)continue;
if((ans[k]>>j&1)==0) flag=0;
}
if(flag) ans[i]-=(1<<j);
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
}
main()
{
solve();
}

浙公网安备 33010602011771号