10.7 2017 CCPC FINAL
只有自己写/补的题。
C.Rich Game√
//简单二分。
#include <bits/stdc++.h>
#define gc() getchar()
typedef long long LL;
const int N=1e5+5;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
bool Check(int win,int x,int y,int k)
{
int now=11*(k-win)*y, tmp=11*x-9*y;
return 1ll*win*tmp>=now;
}
int main()
{
for(int Ts=1,TS=read(); Ts<=TS; ++Ts)
{
int y=read(),x=read(),K=read();
if(x<y) {printf("Case #%d: %d
",Ts,K); continue;}
int l=0,r=K,mid,ans=0;
while(l<=r)
if(Check(mid=l+r>>1,x,y,K)) ans=mid, l=mid+1;
else r=mid-1;
printf("Case #%d: %d
",Ts,ans);
}
return 0;
}
E.Evil Forest√
//签到题
#include <bits/stdc++.h>
#define gc() getchar()
typedef long long LL;
const int N=1e5+5;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
int main()
{
for(int Ts=read(),T=1; T<=Ts; ++T)
{
int n=read(),ans=0;
for(int i=1; i<=n; ++i)
{
int a=read(),b=a/10;
if(b*10<a) ++b;
ans+=a+b;
}
printf("Case #%d: %d
",T,ans);
}
return 0;
}
I.Inkopolis(模拟)(√)
(Description)
给定一棵基环树,每条边有一个颜色(c)。(m)次修改一条边的颜色,每次修改输出当前的边连通块个数。
边连通定义为两条边颜色相同即为连通。
(Tleq 100, n,mleq 2*10^5, sigma n,mleq 10^6)。
(Solution)
对于树的情况很简单,只需要随便判一下就OK了。
树+一个环的情况,设环为(u->w->v->u),其中(LCA(u,v)=w)。
若修改边不在环上和树一样;否则要判断几种情况。
可以发现我们只要能维护查询(u->w->v)整条路径的边是否同色就可以了。
因为没有修改不需要树剖(写了但是HDU栈溢出。。扩栈也没用)(可是网上的都有DFS啊/whl/kk),用multiset维护环上的边就ok。
代码栈溢出了,不想再写了,用set感觉不难写啊,懒得看网上那么长的代码。。
#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include <bits/stdc++.h>
#include <map>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define gc() getchar()
typedef long long LL;
const int N=2e5+25;
int Ans,Index,Tag,Enum,col[N],H[N],nxt[N<<1],to[N<<1],cole[N<<1],son[N],top[N],dep[N],fa[N],id[N],sz[N];
bool vis[N];
std::unordered_map<int,int> mp[N];
struct Segment_Tree
{
#define S N<<2
int cov[S],A[N];
#undef S
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
inline void Update(int rt)
{
if(!cov[ls]||!cov[rs]) cov[rt]=0;
else cov[rt]=(cov[ls]==cov[rs])*cov[ls];
}
void Build(int l,int r,int rt)
{
if(l==r) {cov[rt]=A[l]; return;}
int m=l+r>>1;
Build(lson), Build(rson), Update(rt);
}
void Modify(int l,int r,int rt,int p)
{
if(l==r) {cov[rt]=A[p]; return;}
int m=l+r>>1;
p<=m ? Modify(lson,p) : Modify(rson,p);
Update(rt);
}
int Query(int l,int r,int rt,int id,int R)
{
if(id<=l && r<=R) return cov[rt];
int m=l+r>>1;
if(id<=m)
{
int lv=Query(lson,id,R);
if(m<R)
{
int rv=Query(rson,id,R);
return lv&&rv?(lv==rv)*lv:0;
}
return lv;
}
return Query(rson,id,R);
}
}T;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
inline void AE(int u,int v,int c)
{
++mp[u][c], ++mp[v][c];
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, cole[Enum]=c;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, cole[Enum]=c;
}
void DFS1(int x)
{
int mx=0; vis[x]=1, sz[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=fa[x])
{
if(vis[v]) Tag=i;
else
{
if(x!=1 && cole[i]==col[x]) --Ans;
col[v]=cole[i], fa[v]=x, dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v], sz[v]>mx&&(mx=sz[v],son[x]=v);
}
}
}
void DFS2(int x,int tp)
{
vis[x]=1;
top[x]=tp, T.A[id[x]=++Index]=col[x];
if(son[x])
{
DFS2(son[x],tp);
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=fa[x] && v!=son[x] && i!=Tag && (i^1)!=Tag && !vis[v])
DFS2(v,v);
}
}
int Query(int u,int v,int n)
{
int ans=-1;
while(top[u]!=top[v]&&ans)
{
if(dep[top[u]]<dep[top[v]]) std::swap(u,v);
int t=T.Query(2,n,1,id[top[u]],id[u]), u=fa[top[u]];
if(ans==-1) ans=t;
else if(ans&&t) ans=(ans==t)*t;
else ans=0;
}
if(u==v) return ans;
if(dep[u]>dep[v]) std::swap(u,v);
int t=T.Query(2,n,1,son[id[u]],id[v]);
if(ans==-1) ans=t;
else if(ans&&t) ans=(ans==t)*t;
else ans=0;
return ans;
}
int Check(int A,int B,int C,int n)
{
int x=mp[A][C],y=mp[B][C];
if(!x && !y) return 0;
int t=Query(A,B,n);
if(t==C) return 1;
if(x && y) return 2;
return 1;
}
int main()
{
static bool Tmp[N];
// int size = 256 << 20; // 256MB
// char *p = (char*)malloc(size) + size;
// __asm__("movl %0, %%esp
" :: "r"(p));
for(int Ts=1,TS=read(); Ts<=TS; ++Ts)
{
printf("Case #%d:
",Ts);
int n=read(),Q=read();
Enum=1, memset(H,0,n+2<<2), memset(vis,0,n+2), memset(Tmp,0,n+2);
for(int i=1,u,v; i<=n; ++i) u=read(),v=read(),AE(u,v,read());
Ans=n, Tag=0, Index=0, dep[1]=1, fa[1]=0, DFS1(1);
memset(vis,0,n+2);
DFS2(1,1);
int A=to[Tag],B=to[Tag^1],C=cole[Tag];
if(A>B) std::swap(A,B);
--mp[A][C], --mp[B][C];
for(int i=H[1],v; i; i=nxt[i])
if(i!=Tag && (i^1)!=Tag)
if(Tmp[col[v]]) --Ans;
else Tmp[col[v]]=1;
#define S 2,n,1
T.Build(S);
int las=Check(A,B,C,n);
Ans-=las;
// printf("Init Ans:%d
",Ans);
for(int i=1; i<=Q; ++i)
{
int x=read(),y=read(),c=read();
if(x>y) std::swap(x,y);
if(x==A && y==B)
Ans+=las, las=Check(A,B,C=c,n), Ans-=las;
else
{
if(dep[x]>dep[y]) std::swap(x,y);
int t=col[y];
if(mp[x][t]>1) ++Ans;
if(mp[y][t]>1) ++Ans;
--mp[x][t], --mp[y][t];
col[y]=c, ++mp[x][c], ++mp[y][c];
if(mp[x][c]>1) --Ans;
if(mp[y][c]>1) --Ans;
T.A[id[y]]=c, T.Modify(S,id[y]);
Ans+=las, las=Check(A,B,C,n), Ans-=las;
}
printf("%d
",Ans);
}
for(int i=1; i<=n; ++i) mp[i].clear();
}
return 0;
}
J.Subway Chasing(差分约束)√
对每个限制,可以发现能拆成若干不等式。
然后就是差分约束了(但是要判的情况有点多)。
注意(i
ightarrow i+1)连边。
#include <bits/stdc++.h>
#define gc() getchar()
typedef long long LL;
const int N=5e3+5,M=4e5+5;
const LL INF=1e16;
int Enum,H[N],nxt[M],to[M],val[M],tm[N];
LL dis[N];
bool inq[N];
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
inline void AE(int u,int v,int w)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
}
bool SPFA(int n)//0~n-1
{
std::queue<int> q;
for(int i=0; i<=n; ++i) dis[i]=-INF, tm[i]=0;
tm[0]=dis[0]=0, q.push(0);
while(!q.empty())
{
int x=q.front(); q.pop();
inq[x]=0;
for(int i=H[x],v; i; i=nxt[i])
if(dis[v=to[i]]<dis[x]+val[i])
{
dis[v]=dis[x]+val[i];
if(!inq[v])
{
if(++tm[v]>n+1) return 0;
inq[v]=1, q.push(v);
}
}
}
return 1;
}
int main()
{
for(int Ts=1,TS=read(); Ts<=TS; ++Ts)
{
int n=read(),m=read(),K=read();
Enum=0, memset(H,0,n+2<<2), memset(inq,0,N+2), memset(tm,0,N+2<<2);
for(int i=1; i<=m; ++i)
{
int A=read(),B=read(),C=read(),D=read();
if(A==B)
{
if(C==D) AE(A-1,C-1,K), AE(C-1,A-1,-K);
else A==C?AE(A-1,C,K+1):(AE(C-1,A-1,-(K-1)),AE(A-1,C,K+1));
}
else
{
if(C==D) B==C?AE(A-1,C-1,K+1):(AE(C-1,A,-(K-1)),AE(A-1,C-1,K+1));
else if(B==C) AE(A-1,B,K+1);
else if(A==C) AE(A-1,A,K+1);
else AE(C-1,A,-(K-1)),AE(A-1,C,K+1);
}
}
for(int i=1; i<n; ++i) AE(i-1,i,1), AE(i,i-1,-2e9);
printf("Case #%d:",Ts);
int f=SPFA(n);
if(!f) puts(" IMPOSSIBLE");
else
{
for(int i=0; i<n-1; ++i) printf(" %lld",std::min(dis[i+1]-dis[i],(LL)2e9));
puts("");
}
}
return 0;
}