你们啊,我感觉你们AHOI还要学习,你们非常熟悉NOIP的这一套难度。
你们毕竟TOO YOUNG,你明白我的意思吗?我告诉你们,我是身经百战了,见得多啊。NOIP的哪一个考试我没有做过?你们要知道强省的OI比你们不知要高到哪里去了,哎,我也被他们虐。
OI啊,还是要提高自己的知识水平,晓得不晓得啊?唉,我也替你们着急啊,真的。你们有一个好,NOIP跑到什么地方,比其他的强省OI跑得还快,但是问来问去的问题啊,都TOO SIMPLE,SOMETIMES NAIVE。懂了没有?懂不懂得?
SDOI比AHOI不知要高到哪里去了。
排序:
顺序无关,爆搜大法吼
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; typedef long long LL; const int N=1<<12; int w[N],n; LL fac[N],Ans; void Up(int x,int y,int t) { while(t--) swap(w[x],w[y]), x++,y++; } void dfs(int Now,int s) { if(Now==n) { Ans+=fac[s]; return; } int num=0,pos[5]={}; for(int i=0;i<(1<<n)&&num<=2;i+=1<<Now+1) if(w[i+(1<<Now)-1]+1!=w[i+(1<<Now)]) pos[++num]=i; if(num>2) return; if(num==0) dfs(Now+1,s); else if(num==1) { int p=pos[1]; if(w[p+(1<<Now+1)-1]+1==w[p]) Up(p,p+(1<<Now),1<<Now), dfs(Now+1,s+1), Up(p,p+(1<<Now),1<<Now); } else { int p1=pos[1],p2=pos[2]; if(w[p1+(1<<Now)-1]+1==w[p2+(1<<Now)]&&w[p2+(1<<Now)-1]+1==w[p1+(1<<Now)]) Up(p1,p2,1<<Now), dfs(Now+1,s+1), Up(p1,p2,1<<Now), Up(p1+(1<<Now),p2+(1<<Now),1<<Now), dfs(Now+1,s+1), Up(p1+(1<<Now),p2+(1<<Now),1<<Now); if(w[p2+(1<<Now)-1]+1==w[p1]&&w[p2+(1<<Now+1)-1]+1==w[p1+(1<<Now)]) Up(p1,p2+(1<<Now),1<<Now), dfs(Now+1,s+1), Up(p1,p2+(1<<Now),1<<Now); if(w[p1+(1<<Now)-1]+1==w[p2]&&w[p1+(1<<Now+1)-1]+1==w[p2+(1<<Now)]) Up(p2,p1+(1<<Now),1<<Now), dfs(Now+1,s+1), Up(p2,p1+(1<<Now),1<<Now); } } int main() { scanf("%d",&n); fac[0]=1; for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i; for(int i=0;i<1<<n;i++) scanf("%d",&w[i]); dfs(0,0); cout<<Ans<<endl; return 0; }
寻宝游戏:
很像虚树啊,显然按dfs序跑是最优的= =set大法吼
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; set<int> T; typedef set<int>::iterator Lzz; typedef long long LL; const int N=300005; int pos[N],dfn[N],lg[N],Index,e[N],next[N],G[N],Len[N],tot,n,m; LL Ans,dis[N],Min[N][20]; bool flag[N]; void adde(int u,int v,int l) { e[++tot]=v;next[tot]=G[u];G[u]=tot;Len[tot]=l; } void dfs(int u,int p) { pos[u]=++Index; dfn[Index]=u; Min[Index][0]=dis[u]; for(int v,i=G[u];i;i=next[i]) if((v=e[i])!=p) dis[v]=dis[u]+Len[i], dfs(v,u), Min[++Index][0]=dis[u]; } void Prepare() { for(int i=2;i<=Index;i++) lg[i]=lg[i>>1]+1; for(int j=1;j<=lg[Index];j++) for(int i=1;i+(1<<j)-1<=Index;i++) Min[i][j]=min(Min[i][j-1],Min[i+(1<<j-1)][j-1]); } LL dist(int u,int v) { int x=pos[u],y=pos[v]; if(x>y) swap(x,y); int l=lg[y-x+1]; return dis[u]+dis[v]-2*min(Min[x][l],Min[y-(1<<l)+1][l]); } void Update(int u) { flag[u]^=1; if(flag[u]==1) { if(T.size()) { Lzz it=T.insert(pos[u]).first; Lzz A,B; if(it==T.begin()) A=T.end(),A--; else A=it,A--; it++; if(it==T.end()) B=T.begin(); else B=it; Ans+=dist(u,dfn[*A])+dist(u,dfn[*B])-dist(dfn[*A],dfn[*B]); } else T.insert(pos[u]); } else { if(T.size()>1) { Lzz it=T.find(pos[u]); Lzz A,B; if(it==T.begin()) A=T.end(),A--; else A=it,A--; it++; if(it==T.end()) B=T.begin(); else B=it; Ans-=dist(u,dfn[*A])+dist(u,dfn[*B])-dist(dfn[*A],dfn[*B]); T.erase(pos[u]); } else T.erase(pos[u]); } } int main() { scanf("%d%d",&n,&m); for(int i=1,u,v,l;i<n;i++) scanf("%d%d%d",&u,&v,&l), adde(u,v,l), adde(v,u,l); dfs(1,0); Prepare(); while(m--) { int u; scanf("%d",&u); Update(u); printf("%lld\n",Ans); } return 0; }
序列统计:
原根= =想到原根之后就好办了= =NTT快速幂(模数太显眼了)
程序见http://wuzuofan.is-programmer.com/posts/88375.html NTT模板
星际战争:
二分+网络流判定。。。
程序见http://wuzuofan.is-programmer.com/posts/88375.html DINIC模板
约数和个数:
莫比乌斯反演。。。
程序见http://wuzuofan.is-programmer.com/posts/88375.html MobiusInversion模板
道路修建:
堵塞的交通即视感= =线段树乱搞。。。
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; const int N=100005; int Li[N][2],Ro[N],n,m; struct status { int Max_Li,l,r,Len,lmax,rmax,lpos,rpos,Num; status(){} status(int pos) { l=r=lpos=rpos=pos; lmax=rmax=Len=Ro[pos]; Max_Li=0; Num=1; } }T[N<<2]; status operator+(const status& Lc,const status& Rc) { status x; int W=max(Li[Lc.r][0],Li[Lc.r][1]),Max=max(W,max(Lc.rmax,Rc.lmax)); x.Max_Li=max(max(Lc.Max_Li,Rc.Max_Li),W); x.l=Lc.l; x.r=Rc.r; x.Len=Lc.Len+Rc.Len+Li[Lc.r][0]+Li[Lc.r][1]-Max; x.Num=Lc.Num+Rc.Num; x.lpos=Lc.lpos; x.lmax=Lc.lmax; x.rpos=Rc.rpos; x.rmax=Rc.rmax; if(Ro[Lc.rpos]==Max) { x.Num--; if(Lc.Num==1) x.lpos=Rc.lpos, x.lmax=max(max(Lc.Max_Li,Rc.lmax),W); } else if(Ro[Rc.lpos]==Max) { x.Num--; if(Rc.Num==1) x.rpos=Lc.rpos, x.rmax=max(max(Rc.Max_Li,Lc.rmax),W); } return x; } #define Lc (x<<1) #define Rc (x<<1|1) #define Mid (l+r>>1) void Build(int x,int l,int r) { if(l==r) T[x]=status(l); else Build(Lc,l,Mid), Build(Rc,Mid+1,r), T[x]=T[Lc]+T[Rc]; } void Change_Ro(int x,int l,int r,int p) { if(l==r) T[x]=status(l); else { if(p<=Mid) Change_Ro(Lc,l,Mid,p); else Change_Ro(Rc,Mid+1,r,p); T[x]=T[Lc]+T[Rc]; } } void Change_Li(int x,int l,int r,int p) { if(p<Mid) Change_Li(Lc,l,Mid,p); else if(p>Mid) Change_Li(Rc,Mid+1,r,p); T[x]=T[Lc]+T[Rc]; } status Ask(int x,int l,int r,int L,int R) { if(L<=l&&r<=R) return T[x]; if(R<=Mid) return Ask(Lc,l,Mid,L,R); else if(L>Mid) return Ask(Rc,Mid+1,r,L,R); return Ask(Lc,l,Mid,L,R)+Ask(Rc,Mid+1,r,L,R); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<n;i++) scanf("%d",&Li[i][0]); for(int i=1;i<n;i++) scanf("%d",&Li[i][1]); for(int i=1;i<=n;i++) scanf("%d",&Ro[i]); Build(1,1,n); while(m--) { char op[10]; scanf("%s",op); if(op[0]=='C') { int x1,y1,x2,y2,w; scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&w); if(y1==y2) Ro[y1]=w, Change_Ro(1,1,n,y1); else { if(y1>y2) swap(y1,y2); Li[y1][x1-1]=w, Change_Li(1,1,n,y1); } } else { int x,y; scanf("%d%d",&x,&y); printf("%d\n",Ask(1,1,n,x,y).Len); } } return 0; }