拓扑结构+差分约束+SLF最长路+扩欧
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑结构+差分约束+SLF最长路+扩欧相关的知识,希望对你有一定的参考价值。
倦怠,但还不能休息,我的牌还没有到手~
E. Exchanging Gifts
997m过了,超时了就多交几次就可能过吧……可以把vector改成链式前向行,vector改为二维数组,会优化100ms左右。
#include <bits/stdc++.h>
#define endl '\\n'
//#define int long long
#define ll long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>
#define re register
using namespace std;
const int N =1e6+5;
const int inf=1e18;
const int mod=998244353;
const double eps=1e-8;
int n,ind[N];
ll num[N];
bool vis[N],tag[N];
vector<int>v[N],e[N];
unordered_map<ll,ll>mp;
inline void bfs()
queue<int>q;
q.push(n);
while(!q.empty())
int cur=q.front();q.pop();
if(vis[cur]) continue;
vis[cur]=1;
for(int v:e[cur])
ind[v]++;
q.push(v);
num[n]=1;
q.push(n);
while(!q.empty())
int u=q.front();q.pop();
for(int v:e[u])
num[v]+=num[u];
ind[v]--;
if(!ind[v]) q.push(v);
if(tag[u])
for(auto x:v[u])
mp[x]+=num[u];
inline void solve()
cin>>n;
for(re int i=0;i<=n;i++)
e[i].clear();v[i].clear();
ind[i]=tag[i]=num[i]=vis[i]=0;
mp.clear();
for(re int i=1;i<=n;i++)
int op;cin>>op;
if(op==1)
tag[i]=1;
int m;cin>>m;
for(int j=1;j<=m;j++)
int x;cin>>x;
v[i].push_back(x);
else
int x,y;cin>>x>>y;
e[i].push_back(x);e[i].push_back(y);
bfs();
ll sum=0,mx=0;
for(auto x:mp)
sum+=x.second,mx=max(mx,x.second);
if(mx>=sum-mx) cout<<2ll*(sum-mx)<<endl;
else cout<<sum<<endl;
signed main()
ios;
int T;
cin>>T;
while(T--)
solve();
return 0;
A. Artful Paintings
二分+差分约束
思路:
1.两个未知量可能想到扩欧,本题是毫不相关。而且本题三个变量,需要枚举出sum[n]的值
2.采用求最长路的SLF双端队列实现操作。
4.四类见图方式:sum[r]-sum[l-1]>=k
、sum[l-1]-sum[r]>=k-sum[n]
、sum[i]-sum[i-1]>=0
、sum[i-1]-sum[i]>=-1
、sum[n]-sum[0]>=x
、sum[0]-sum[n]>=-n
#include <bits/stdc++.h>
#define endl '\\n'
//#define int long long
#define ll long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>
#define re register
using namespace std;
const int N =7e5+5;
const int inf=1e18;
const int mod=998244353;
const double eps=1e-8;
int n,m1,m2,cnt;
struct border
int l,r,w;
b1[N],b2[N];
int head[N],dis[N],vis[N],ct[N];
struct node
int to,nxt,w;
e[N];
void add(int from,int to,int w)
e[++cnt].to=to;
e[cnt].nxt=head[from];
e[cnt].w=w;
head[from]=cnt;
int check(int x) //求最长路
for(int i=0;i<=n;i++) head[i]=-1,dis[i]=-1e9,vis[i]=ct[i]=0;
cnt=0;
for(int i=1;i<=m1;i++)
int l=b1[i].l,r=b1[i].r,w=b1[i].w;
add(l-1,r,w);
for(int i=1;i<=m2;i++)
int l=b2[i].l,r=b2[i].r,w=b2[i].w;
add(r,l-1,w-x);
for(int i=1;i<=n;i++)
add(i-1,i,0);add(i,i-1,-1);
add(0,n,x);add(n,0,-x);
vis[0]=ct[0]=1;
dis[0]=0;
deque<int>q;
q.push_back(0);
while(!q.empty())
int u=q.front();
q.pop_front();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].nxt)
int v=e[i].to,w=e[i].w;
if(dis[v]<dis[u]+w)
dis[v]=dis[u]+w;
ct[v]=ct[u]+1;
if(ct[v]>n+1)
return 0;
if(!vis[v])
vis[v]=1;
if(!q.empty()&&dis[v]>dis[q.front()])
q.push_front(v);
else
q.push_back(v);
return 1;
void solve()
cin>>n>>m1>>m2;
for(int i=1;i<=m1;i++)
int l,r,w;cin>>l>>r>>w;
b1[i]=l,r,w;
for(int i=1;i<=m2;i++)
int l,r,w;cin>>l>>r>>w;
b2[i]=l,r,w;
int l=0,r=n,mid,ans;
while(l<=r)
mid=(l+r)/2;
if(check(mid))
r=mid-1,ans=mid;
else
l=mid+1;
cout<<ans<<endl;
signed main()
//ios;
int T;
cin>>T;
while(T--)
solve();
return 0;
G - 01Sequence
要废了 。。。最短路都写错了 ,哭
#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
#define ll long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>
#define re register
using namespace std;
const int N =7e5+5;
const int inf=1e18;
const int mod=998244353;
const double eps=1e-8;
int n,m,dis[N];
vector<PII>g[N];
bool vis[N];
void dij()
for(int i=0;i<=n;i++) dis[i]=inf;
dis[0]=0;
priority_queue<PII,vector<PII>,greater<PII>>q;
q.push(0,0);
while(q.size())
int u=q.top().second,d=q.top().first;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(auto x:g[u])
int v=x.first,w=x.second;
if(dis[v]>d+w)
dis[v]=d+w;
q.push(dis[v],v);
void solve()
cin>>n>>m;
for(int i=1; i<=m; i++)
int l,r,x;cin>>l>>r>>x;
x=r-l+1-x;
g[l-1].push_back(r,x);
for(int i=0; i<=n-1; i++)
g[i].push_back(i+1,1);
g[i+1].push_back(i,0);
dij();
for(int i=1; i<=n; i++)
cout<<((dis[i]-dis[i-1])^1)<<" ";
cout<<endl;
signed main()
ios;
// int T;
// cin>>T;
// while(T--)
solve();
return 0;
D. ConstructOR
思路:
很容易想到要构造的那个数肯定是d的倍数,同时二进制a、b中出现的1.
令k=a|b,此时k不一定是d的倍数,我们只需要找到一个k是d的倍数。
可得出方程:r=d-k%d,也就是说k需要减去这样一个数r才会是d的倍数。
因此:x==r(mod d)
,由于低位的1会重复,因此左移30位2^30*x==r(mod d)
#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
//#define ll long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define PII pair<int,int>
#define re register
using namespace std;
const int以上是关于拓扑结构+差分约束+SLF最长路+扩欧的主要内容,如果未能解决你的问题,请参考以下文章
POJ.1752.Advertisement(差分约束 最长路SPFA)
HDU.1529.Cashier Employment(差分约束 最长路SPFA)