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

题目描述

有一个长为 n 的数列 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也确实变快了

posted on 2018-03-07 21:31  scau_bi  阅读(202)  评论(0编辑  收藏  举报

导航