wannafly 挑战赛9 E 组一组 (差分约束)
链接:https://www.nowcoder.com/acm/contest/71/E
时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 65536K,其他语言131072K
Special Judge, 64bit IO Format: %lld
Special Judge, 64bit IO Format: %lld
题目描述
有一个长为 n 的数列 A,其中有 m 个限制条件,条件有两种:
1、对于区间 [l,r],其区间元素按位或和等于 x
2、对于区间 [l,r],其区间元素按位与和等于 x
求出一个数列 A,使得满足给定的 m 个条件,保证有解。
1、对于区间 [l,r],其区间元素按位或和等于 x
2、对于区间 [l,r],其区间元素按位与和等于 x
求出一个数列 A,使得满足给定的 m 个条件,保证有解。
输入描述:
输入第一行两个正整数 n,m,意义如上
接下来 m 行,每行四个整数 op,l,r,x,表示一组限制
op = 1 表示是限制 1,op = 2 表示是限制 2
输出描述:
输出仅一行,n 个整数 ai表示数列 A。要求 0 <= ai< 1e9
示例1
输入
4 3 1 1 2 9 2 3 4 2 1 2 3 11
输出
1 9 2 6
备注:
1<=n,m<=10^5, 1<=l<=r<=n, 0<=x<2^20
////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
1 #include <bits/stdc++.h> 2 #define mst(a,b) memset((a),(b), sizeof a) 3 #define lowbit(a) ((a)&(-a)) 4 #define IOS ios::sync_with_stdio(0);cin.tie(0); 5 using namespace std; 6 typedef long long ll; 7 typedef unsigned long long ull; 8 typedef pair<int,int> pii; 9 const int mod=1e9+7; 10 const int maxn=1e5+10; 11 int od[maxn],l[maxn],r[maxn],x[maxn]; 12 int ans[maxn]; 13 bool vis[maxn]; 14 int head[maxn],dist[maxn]; 15 int s[maxn]; 16 struct edge{ 17 int to,nx,val; 18 }ed[maxn<<3];int cnt; 19 20 void addedge(int from,int to,int val){ 21 ed[++cnt].to=to;ed[cnt].val=val; 22 ed[cnt].nx=head[from];head[from]=cnt; 23 } 24 25 void init(int n){ 26 cnt=0; 27 mst(head,0);mst(s,0); 28 for(int i=0;i<n;++i){ 29 addedge(i+1,i,1); 30 addedge(i,i+1,0); 31 } 32 } 33 34 void spfa(int n){ 35 mst(vis,false); 36 mst(dist,0x3f); 37 vis[0]=true;dist[0]=0; 38 stack<int>sta; 39 sta.push(0); 40 while(!sta.empty()){ 41 int u=sta.top();sta.pop(); 42 vis[u]=false; 43 for(int i=head[u];i;i=ed[i].nx){ 44 int v=ed[i].to; 45 if(dist[v]>dist[u]+ed[i].val){ 46 dist[v]=dist[u]+ed[i].val; 47 if(!vis[v]){ 48 vis[v]=true; 49 sta.push(v); 50 } 51 } 52 } 53 } 54 } 55 56 int main() { 57 #ifdef local 58 freopen("inpp","r",stdin); 59 // freopen("outpp","w",stdout); 60 #endif 61 int n,m;scanf("%d%d",&n,&m); 62 for(int i=1;i<=m;++i)scanf("%d%d%d%d",&od[i],&l[i],&r[i],&x[i]); 63 for(int d=19;d>=0;--d){ 64 init(n); 65 for(int i=1;i<=m;++i){ 66 if(od[i]==1){ 67 if((x[i]>>d)&1)addedge(l[i]-1,r[i],-1); 68 else addedge(r[i],l[i]-1,0); 69 }else{ 70 if((x[i]>>d)&1)addedge(l[i]-1,r[i],l[i]-1-r[i]),++s[l[i]],--s[r[i]+1]; 71 else addedge(r[i],l[i]-1,r[i]-l[i]); 72 } 73 } 74 for(int i=1;i<=n;++i)s[i]+=s[i-1]; 75 for(int i=1;i<=n;++i)s[i]=s[i]?1:0; 76 for(int i=1;i<=n;++i)s[i]+=s[i-1],addedge(0,i,-s[i]); 77 spfa(n); 78 for(int i=1;i<=n;++i){ 79 ans[i]<<=1; 80 if(dist[i]-dist[i-1])ans[i]|=1; 81 } 82 } 83 for(int i=1;i<=n;++i)printf("%d\n",ans[i]); 84 return 0; 85 }
很神奇,,,,代码一直超时,然后对比了了别人的代码,加了这几行,就过了,不是很理解为什么会快那么多
1 for(int i=1;i<=n;++i)s[i]+=s[i-1]; 2 for(int i=1;i<=n;++i)s[i]=s[i]?1:0; 3 for(int i=1;i<=n;++i)s[i]+=s[i-1],addedge(0,i,-s[i]);
然后把queue换成stack也确实变快了