csp2019备赛之刷题赛-round3

牧云@^-^@ 提交于 2019-12-03 10:45:27

csp2019备赛之刷题赛-round3

link to this contest

C. Winner

大意:有$n$个人打淘汰赛,每个人有$3$个权值,只要有一个权值大于对方就有可能获胜,问每个人是否有可能夺冠

$n \leq 10^5$

题解:对于三维权值,每一维都排一次序,权值大的向权值小的连边,如果有权值相同,就开两个出入的虚点,如果存在一条$x-->y$的路径就说明$x$可能打败$y$,然后缩点,没有入度的那个块里面的点都可能拿冠军

  1 #include<bits/stdc++.h>
  2 namespace csx_std {
  3     using namespace std;
  4     typedef long long ll;
  5     #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
  6     #define For(i,a,b) for (register int i=(a);i>=(b);i--)
  7     #define mem(i,j) memset(i,j,sizeof(i))
  8     #define pii pair<int,int>
  9     #define MP make_pair
 10     #define fi first
 11     #define se second
 12     #define GO(u) for (register int j=first[u];j!=-1;j=nxt[j])
 13     const int N=4e5+5;
 14     const int mod=1e9+7;
 15     inline int qpow(int x,int y) {int ret=1;for (;y;y>>=1,x=1LL*x*x%mod) if (y&1) ret=1LL*ret*x%mod;return ret;}
 16     inline int Inv(int x) {return qpow(x,mod-2);}
 17     inline void upd(int &x,int y) {x=(1LL*x+y)%mod;return;}
 18     inline int chkmax(int &x,int y) {return (x<y)?(x=y,1):0;}
 19     inline int chkmin(int &x,int y) {return (x>y)?(x=y,1):0;}
 20     inline int read()
 21     {
 22         int x=0,f=1;
 23         char c=getchar();
 24         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
 25         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
 26         return f*x;
 27     }
 28     inline void write(int x)
 29     {
 30         if (x<0) x=-x,putchar('-');
 31         if (x>9) write(x/10);
 32         putchar(x%10+'0');
 33         return;
 34     }
 35 }
 36 using namespace csx_std;
 37 int n,q,Q[N],ans[N],vis[N],dfn[N],low[N],stck[N],dfnn=0;
 38 int bl[N],du[N],cnt,top=0,siz[N],gp=0,tag=0;
 39 int tot=0,first[N],nxt[N];
 40 struct E
 41 {
 42     int u,v;
 43 }e[N];
 44 inline void add(int u,int v)
 45 {
 46     if (!v) return;
 47     tot++;
 48     nxt[tot]=first[u];
 49     first[u]=tot;
 50     e[tot]=(E){u,v};
 51 //    printf("(%d,%d)\n",u,v);
 52     return;
 53 }
 54 struct data
 55 {
 56     int a,b,c,id;
 57 }f[N];
 58 bool cmp1(const data x,const data y) {return x.a<y.a;}
 59 bool cmp2(const data x,const data y) {return x.b<y.b;}
 60 bool cmp3(const data x,const data y) {return x.c<y.c;}
 61 inline void build()
 62 {
 63     int last=0;
 64     sort(f+1,f+n+1,cmp1);
 65     FOR(i,1,n)
 66     {
 67         int r=i;
 68         while (f[i].a==f[r+1].a) r++;
 69         if (i<r)
 70         {
 71             cnt++;
 72             add(cnt,last);
 73             FOR(j,i,r) add(f[j].id,cnt);
 74             cnt++;
 75             FOR(j,i,r) add(cnt,f[j].id);
 76             last=cnt;
 77         }
 78         else add(f[i].id,last),last=f[i].id;
 79         i=r;
 80     }
 81     
 82     last=0;
 83     sort(f+1,f+n+1,cmp2);
 84     FOR(i,1,n)
 85     {
 86         int r=i;
 87         while (f[i].b==f[r+1].b) r++;
 88         if (i<r)
 89         {
 90             cnt++;
 91             add(cnt,last);
 92             FOR(j,i,r) add(f[j].id,cnt);
 93             cnt++;
 94             FOR(j,i,r) add(cnt,f[j].id );
 95             last=cnt;
 96         }
 97         else add(f[i].id,last),last=f[i].id;
 98         i=r;
 99     }
100     
101     last=0;
102     sort(f+1,f+n+1,cmp3);
103     FOR(i,1,n)
104     {
105         int r=i;
106         while (f[i].c==f[r+1].c) r++;
107         if (i<r)
108         {
109             cnt++;
110             add(cnt,last);
111             FOR(j,i,r) add(f[j].id,cnt);
112             cnt++;
113             FOR(j,i,r) add(cnt,f[j].id );
114             last=cnt;
115         }
116         else add(f[i].id,last),last=f[i].id;
117         i=r;
118     }
119     return;
120 }
121 inline void Tarjan(int u)
122 {
123     dfn[u]=low[u]=++dfnn;
124     vis[u]=1;
125     stck[++top]=u;
126     GO(u)
127     {
128         int v=e[j].v;
129         if (!dfn[v])
130         {
131             Tarjan(v);
132             chkmin(low[u],low[v]);
133         }
134         else if (vis[v]) chkmin(low[u],dfn[v]);
135     }
136     if (low[u]==dfn[u])
137     {
138         gp++;
139         while (stck[top+1]!=u)
140         {
141             bl[stck[top]]=gp;
142             vis[stck[top]]=0;
143             if (stck[top]<=n) siz[gp]++;
144             top--;
145         }
146     }
147     return;
148 }
149 int main()
150 {
151     mem(first,-1);
152     n=read(),q=read();
153     cnt=n;
154     FOR(i,1,n) f[i].a=read();
155     FOR(i,1,n) f[i].b=read();
156     FOR(i,1,n) f[i].c=read();
157     FOR(i,1,n) f[i].id=i;
158     FOR(i,1,q) Q[i]=read();
159     build();
160     FOR(i,1,cnt) 
161         if (!dfn[i]) Tarjan(i);
162     FOR(i,1,tot) if (bl[e[i].u]!=bl[e[i].v]) du[bl[e[i].v]]++;
163     FOR(i,1,gp) if (!du[i])
164     {
165         tag=i;
166         break;
167     }
168     FOR(i,1,n) if (bl[i]==tag) vis[i]=1;
169     FOR(i,1,q) ans[i]=vis[Q[i]];
170     FOR(i,1,q)
171         if (ans[i]) printf("YES\n");
172         else printf("NO\n");
173     return 0;
174 }
175 /*
176 4 4
177 1 2 3 4
178 1 2 4 3
179 2 1 3 4
180 1
181 2
182 3
183 4
184 */
View Code

F. Explorer

大意:给定一张无向图,每条边有权值范围$[l_i,r_i]$,要经过这条边的条件是你的容量要在$[l_i,r_i]$,现在问你有多少种容量,使得你能从$1$走到$n$

$n,m \leq 10^5 , l,r \leq 10^9$

题解:线段树分治加可撤销并查集,其中我们需要把权值区间离散化,那么我们线段树上的节点不能再使用闭区间了,否则$(mid,mid+1)$之间的权值会蒸发,改成左闭右开的区间就行了

  1 #include<bits/stdc++.h>
  2 namespace csx_std {
  3     using namespace std;
  4     typedef long long ll;
  5     #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
  6     #define For(i,a,b) for (register int i=(a);i>=(b);i--)
  7     #define mem(i,j) memset(i,j,sizeof(i))
  8     #define pii pair<int,int>
  9     #define pb push_back
 10     #define MP make_pair
 11     #define fi first
 12     #define se second
 13     #define GO(u) for (register int j=first[u];j!=-1;j=nxt[j])
 14     const int N=3e5+5;
 15     const int mod=1e9+7;
 16     inline int qpow(int x,int y) {int ret=1;for (;y;y>>=1,x=1LL*x*x%mod) if (y&1) ret=1LL*ret*x%mod;return ret;}
 17     inline int Inv(int x) {return qpow(x,mod-2);}
 18     inline void upd(int &x,int y) {x=(1LL*x+y)%mod;return;}
 19     inline int chkmax(int &x,int y) {return (x<y)?(x=y,1):0;}
 20     inline int chkmin(int &x,int y) {return (x>y)?(x=y,1):0;}
 21     inline int read()
 22     {
 23         int x=0,f=1;
 24         char c=getchar();
 25         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
 26         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
 27         return f*x;
 28     }
 29     inline void write(ll x)
 30     {
 31         if (x<0) x=-x,putchar('-');
 32         if (x>9) write(x/10);
 33         putchar(x%10+'0');
 34         return;
 35     }
 36 }
 37 using namespace csx_std;
 38 int n,m,fa[N],dep[N];
 39 ll ans=0,b[N<<1],len=0;
 40 int in1[N],in2[N],in3[N],in4[N];
 41 struct data
 42 {
 43     int u,v,w;
 44 };
 45 vector <data> vec[N<<2];
 46 inline int getfa(int x) {return (x==fa[x])?x:getfa(fa[x]);}
 47 inline int con(int x,int y)
 48 {
 49     int fx=getfa(x),fy=getfa(y);
 50     return (fx==fy);
 51 }
 52 inline data link(int x,int y)
 53 {
 54     data ret;
 55     int fx=getfa(x),fy=getfa(y);
 56     if (dep[fx]>dep[fy]) swap(x,y),swap(fx,fy);
 57     ret.u=fx,ret.v=fy;
 58     fa[fx]=fy;
 59     if (dep[fx]==dep[fy]) dep[fy]++,ret.w=1;
 60     else ret.w=0;
 61     return ret;
 62 }
 63 inline void del(vector <data> V)
 64 {
 65     For(i,(int)V.size()-1,0)
 66     {
 67         dep[V[i].v]-=V[i].w;
 68         fa[V[i].u]=V[i].u;
 69     }
 70     return;
 71 }
 72 inline void insert(int p,int l,int r,int L,int R,int ith)
 73 {
 74     if (L<=l&&r<=R) {vec[p].pb((data){in1[ith],in2[ith],0});return;}
 75     if (l==r-1) return;
 76     int mid=(l+r)>>1;
 77     if (L<=mid) insert(p<<1,l,mid,L,R,ith);
 78     if (R>mid) insert(p<<1|1,mid,r,L,R,ith);
 79     return;
 80 }
 81 inline void solve(int p,int l,int r)
 82 {
 83     vector <data> rub;
 84     rub.clear();
 85     FOR(i,0,(int)vec[p].size()-1) if (!con(vec[p][i].u,vec[p][i].v)) rub.pb(link(vec[p][i].u,vec[p][i].v));
 86     if (con(1,n)) {ans+=b[r]-b[l];del(rub);return;}
 87     if (l==r-1) {del(rub);return;}
 88     int mid=(l+r)>>1;
 89     solve(p<<1,l,mid);
 90     solve(p<<1|1,mid,r);
 91     del(rub);
 92     return;
 93 }
 94 inline void debug(int p,int l,int r)
 95 {
 96     printf("[%d,%d] : \n",l,r);
 97     FOR(i,0,(int)vec[p].size()-1)
 98     {
 99         printf("(%d,%d) ",vec[p][i].u,vec[p][i].v);
100     }
101     putchar('\n');
102     int mid=(l+r)>>1;
103     if (l==r) return;
104     debug(p<<1,l,mid);
105     debug(p<<1|1,mid+1,r);
106     return;
107 }
108 int main()
109 {
110     n=read(),m=read();
111     FOR(i,1,n) fa[i]=i,dep[i]=1;
112     FOR(i,1,m) in1[i]=read(),in2[i]=read(),in3[i]=read(),in4[i]=read()+1,b[++len]=in3[i],b[++len]=in4[i];
113     sort(b+1,b+len+1);
114     len=unique(b+1,b+len+1)-b-1;
115     FOR(i,1,m) in3[i]=lower_bound(b+1,b+len+1,in3[i])-b,in4[i]=lower_bound(b+1,b+len+1,in4[i])-b;
116     FOR(i,1,m) insert(1,1,len,in3[i],in4[i],i);
117     solve(1,1,len);
118     write(ans),putchar('\n');
119 //    debug(1,1,len);
120     return 0;
121 }
122 /*
123 5 5
124 1 2 10 40
125 2 3 10 20
126 3 5 20 40
127 2 4 10 30
128 4 5 20 40
129 */
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!