POI 2022 Stage I
Kolorowy wąż (kol)
用栈从蛇尾到蛇头记录每一段身体的颜色,每次蛇头变化都认为是新长出了一个蛇头。
对于每个坐标,记录它最后一次是被哪个蛇头经过的,那么根据蛇头版本的差值可以得到对应蛇身相对于蛇头的名次,然后即可在栈中找到对应的颜色。
每次操作的时间复杂度为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include<cstdio> const int N=2005; int n,m,q,i,j,x,y,z,cnt,len,col[N*N],bean[N][N],last[N][N]; char op[9]; inline int ask( int x, int y){ if (x<1||x>n||y<1||y>n) return -1; int o=last[x][y]; if (!o) return -1; o=cnt-o+1; if (o>len) return -1; return col[len-o+1]; } int main(){ scanf ( "%d%d%d" ,&n,&m,&q); while (m--) scanf ( "%d%d%d" ,&i,&j,&z),bean[i][j]=z+1; x=y=cnt=len=last[1][1]=1; while (q--){ scanf ( "%s" ,op); if (op[0]== 'Z' ){ scanf ( "%d%d" ,&i,&j); printf ( "%d\n" ,ask(i,j)); continue ; } if (op[0]== 'G' )x--; else if (op[0]== 'D' )x++; else if (op[0]== 'L' )y--; else y++; if (bean[x][y]){ col[++len]=bean[x][y]-1; bean[x][y]=0; } last[x][y]=++cnt; } } |
Płytkie nawiasowania (ply)
将 '(' 视为,')' 视为,那么需要满足前缀和介于,且总和为。
从左往右模拟,一旦在当前位置发现前缀和不在,就反转当前的括号,一定可以保证代价最小。
时间复杂度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include<cstdio> const int N=1000005; int n,k,i,s,ans; char a[N]; int main(){ scanf ( "%d%d%s" ,&n,&k,a+1); for (i=1;i<=n;i++){ if (a[i]== '(' ){ s++; if (s>k)s-=2,ans++; } else { s--; if (s<0)s+=2,ans++; } } printf ( "%d" ,ans); } |
Pociąg towarowy (poc)
找到表示从左往右贪心匹配出的位置,以及表示从右往左贪心匹配出的位置。
那么中所有值为的位置都可能被匹配,对于这个值出现的所有下标通过差分前缀和打标记即可。
时间复杂度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include<cstdio> const int N=300005; int n,m,k,i,j,a[N],b[N],add[N],del[N],sum[N]; int main(){ scanf ( "%d%d%d" ,&n,&m,&k); for (i=1;i<=n;i++) scanf ( "%d" ,&a[i]); for (i=1;i<=m;i++) scanf ( "%d" ,&b[i]); for (i=j=1;i<=m;i++){ while (a[j]!=b[i])j++; add[j++]++; } for (i=m,j=n;i;i--){ while (a[j]!=b[i])j--; del[j--]++; } for (i=1;i<=n;i++){ j=a[i]; sum[j]+=add[i]; printf ( "%d%c" ,!!sum[j],i<n? ' ' : '\n' ); sum[j]-=del[i]; } } |
Wyprzedzanie (wyp)
相邻两辆车一旦紧靠在一起,它们将永远紧靠在一起,可以合并为一辆车。
提取相邻两辆车合并为一个整体的时间点,然后按时间顺序模拟即可,使用链表+堆维护。
实现的时候,需要使用全整数分数类以避免精度误差。
时间复杂度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #include<cstdio> #include<algorithm> #include<queue> #include<vector> using namespace std; typedef long long ll; typedef __int128 lll; typedef pair< int , int >P; const int N=100005; int n,i,j,state,pre[N],nxt[N],del[N],ans; struct Frac{ ll u,d; Frac(){} Frac(ll _u,ll _d){u=_u,d=_d;} void read(){ scanf ( "%lld%lld" ,&u,&d);} int sgn( const Frac&b) const { lll tmp=((lll)u)*((lll)b.d)-((lll)d)*((lll)b.u); if (!tmp) return 0; return tmp>0?1:-1; } bool operator<( const Frac&b) const { return sgn(b)<0;} bool operator<=( const Frac&b) const { return sgn(b)<=0;} }last; struct Car{ int x,d; Frac v; void read(){ scanf ( "%d%d" ,&x,&d);v.read();} }car[N]; typedef pair<Frac,P>E; priority_queue<E,vector<E>,greater<E> >q; inline void mergeevent( int A, int B){ if (car[A].v<=car[B].v) return ; int delta=car[B].x-car[B].d-car[A].x; ll u=1LL*delta*car[A].v.d*car[B].v.d,d=car[A].v.u*car[B].v.d-car[A].v.d*car[B].v.u; q.push(E(Frac(u,d),P(A,B))); } inline Frac cal( int B, int o){ if (del[B]) return Frac(-1,-1); int delta=car[B].x; if (o==0)delta-=car[B].d; else delta+=car[0].d; ll u=1LL*delta*car[0].v.d*car[B].v.d,d=car[0].v.u*car[B].v.d-car[0].v.d*car[B].v.u; return Frac(u,d); } int main(){ scanf ( "%d%d" ,&n,&car[0].d); car[0].v.read(); for (i=1;i<=n;i++)car[i].read(); for (i=0;i<=n+1;i++){ pre[i]=i-1; nxt[i]=i+1; } for (i=1;i<n;i++)mergeevent(i,i+1); last=Frac(0,1); state=1; for (i=1;i<=n;i++) for (j=0;j<2;j++){ Frac t=cal(i,j); while (!q.empty()&&t.u>=0){ E e=q.top(); int A=e.second.first,B=e.second.second; if (del[B]){ q.pop(); continue ; } if (t<=e.first) break ; last=e.first; q.pop(); car[B].d+=car[A].d; del[A]=1; t=cal(i,j); int C=pre[A]; pre[B]=C; nxt[C]=B; if (C)mergeevent(C,B); } if (t.u<0) continue ; if (t<last) continue ; last=t; if (j==0){ if (state==1)ans++,state=0; } else { if (i<n&&cal(nxt[i],0)<t) continue ; state=1; } } printf ( "%d" ,ans); } |
Zboże (zbo)
动态点分治。时间复杂度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include<cstdio> typedef long long ll; const int N=100005,M=2000005; int n,k,i,x,y,z; int g[N],v[N<<1],w[N<<1],nxt[N<<1],ok[N<<1],ed; int son[N],f[N],all,now,cnt; int G[N],V[2][M],W[M],NXT[M],ED; int s[N],se[N];ll sd[N],sed[N],ans; inline void add( int x, int y, int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;ok[ed]=1;} inline void ADD( int x, int y, int z, int w){V[0][++ED]=y;V[1][ED]=z;W[ED]=w;NXT[ED]=G[x];G[x]=ED;} void findroot( int x, int y){ son[x]=1;f[x]=0; for ( int i=g[x];i;i=nxt[i]) if (ok[i]&&v[i]!=y){ findroot(v[i],x); son[x]+=son[v[i]]; if (son[v[i]]>f[x])f[x]=son[v[i]]; } if (all-son[x]>f[x])f[x]=all-son[x]; if (f[x]<f[now])now=x; } void dfs( int x, int y, int dis){ ADD(x,now,cnt,dis); for ( int i=g[x];i;i=nxt[i]) if (ok[i]&&v[i]!=y)dfs(v[i],x,dis+w[i]); } void solve( int x){ int i; for (i=g[x];i;i=nxt[i]) if (ok[i])cnt++,dfs(v[i],x,w[i]); for (i=g[x];i;i=nxt[i]) if (ok[i]){ ok[i^1]=0; f[0]=all=son[v[i]]; findroot(v[i],now=0); solve(now); } } inline void modify( int x){ ans+=sd[x]; s[x]++; for ( int i=G[x];i;i=NXT[i]){ int A=V[0][i],B=V[1][i],C=W[i]; ans+=sd[A]-sed[B]+1LL*C*(s[A]-se[B]); s[A]++,sd[A]+=C; se[B]++,sed[B]+=C; } } int main(){ scanf ( "%d%d" ,&n,&k); for (ed=i=1;i<n;i++) scanf ( "%d%d%d" ,&x,&y,&z),add(x,y,z),add(y,x,z); f[0]=all=n; findroot(1,0); solve(now); modify(1); while (k--) scanf ( "%d" ,&x),modify(x), printf ( "%lld\n" ,ans*2); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
2017-10-30 XVIII Open Cup named after E.V. Pankratiev. Grand Prix of SPb
2016-10-30 HDU5942 : Just a Math Problem