1.处理内容
图论部
最短路算法 2题
数据结构部
set 1题
链表 1题
分块 1题
hash 1题
单调栈 1题
分治树+数链剖分 1题
数学几何部
FFT 1题
线性筛 1题
2.图论部
(1)dijkstra
没什么好说的直接甩版
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define sta 222222
#define stb 888888
priority_queue >que;
int n,m,a,b,c,tot,first[sta],nxt[stb],goal[stb],dis[stb],to[sta];
void addedge(int a,int b,int c){
++tot;nxt[tot]=first[a];first[a]=tot;goal[tot]=b;dis[tot]=c;
++tot;nxt[tot]=first[b];first[b]=tot;goal[tot]=a;dis[tot]=c;
return ;
}
void dijkstra(){
for(int i=1;i<=n;++i)
to[i]=999999999999999;
to[1]=0;
que.push(make_pair(-to[1],1));
while(!que.empty()){
int u=que.top().second;
que.pop();
for(int p=first[u];p;p=nxt[p])
if(to[goal[p]]>to[u]+dis[p]){
to[goal[p]]=to[u]+dis[p];
que.push(make_pair(-to[goal[p]],goal[p]));
}
}
}
signed main(){
n=read();m=read();
for(int i=1;i<=m;++i){
a=read();b=read();c=read();
addedge(a,b,c);
}
dijkstra();
write(to[n]);
return 0;
}
(2)SPFA
同样没什么好说的直接甩版
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define sta 22222
#define stb 44444
queueque;
int tot,nxt[stb],goal[stb],dis[stb],n,m,to[sta],first[sta],a,b,c;
bool exi[sta];
void addedge(int a,int b,int c){
++tot;nxt[tot]=first[a];first[a]=tot;goal[tot]=b;dis[tot]=c;
return ;
}
void spfa(){
for(int i=1;i<=n;++i)
to[i]=9999999999999999;
to[1]=0;
que.push(1);exi[1]=true;
while(!que.empty()){
int u=que.front();
exi[u]=false;
que.pop();
for(int p=first[u];p;p=nxt[p])
if(to[goal[p]]>to[u]+dis[p]){
to[goal[p]]=to[u]+dis[p];
if(!exi[goal[p]]){
que.push(goal[p]);
exi[goal[p]]=true;
}
}
}
return ;
}
signed main(){
n=read();m=read();
for(int i=1;i<=m;++i){
a=read();b=read();c=read();
addedge(a,b,c);
}
spfa();
write(to[n]);
return 0;
}
3.数据结构部
(1)宠物收养所(HNOI2004)
题面在这里http://www.lydsy.com/JudgeOnline/problem.php?id=1208
这个题可以作为很多题的模板,但是今天我们用set
感谢scarlyw的帮助
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mod 1000000
using namespace std;
inline long long read(){
long long i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define inf 0x3f3f3f3f
sets;
set::iterator it=s.begin(); //使set可被遍历
int n,x,y,ans,tmp,l,r;
signed main(){
n=read();
s.insert(inf);
s.insert(-inf);
for(int i=1;i<=n;++i){
x=read();y=read();
if(s.size()==2)
tmp=x;
if(x==tmp)
s.insert(y);
else{
r=*s.lower_bound(y);
l=*--s.lower_bound(y);//指向第一个小于等于y的当前元素
if(y-l<=r-y){
ans=(y-l+ans)%mod;
s.erase(l);
}else{
ans=(r-y+ans)%mod;
s.erase(r);
}
}
}
write(ans);
return 0;
}
(2)营业额统计(HNOI2002)
题面照例甩链接http://www.lydsy.com/JudgeOnline/problem.php?id=1588
建立一个带插入顺序的双向链表即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 33333
struct data{
int val,pos;
int l,r;
}d[stan];
inline bool cmp(data a,data b){
return a.val1;--i){
int x=idx[i];
if(d[x].l&&d[x].r){
ans+=min(d[x].val-d[d[x].l].val,d[d[x].r].val-d[x].val);
d[d[x].l].r=d[x].r;
d[d[x].r].l=d[x].l;
}else if(!d[x].l){
ans+=d[d[x].r].val-d[x].val;
d[d[x].r].l=0;
}else{
ans+=d[x].val-d[d[x].l].val;
d[d[x].l].r=0;
}
}
write(ans);
return 0;
}
(3)弹飞绵羊(HNOI2010)
题面还是在这里http://www.lydsy.com/JudgeOnline/problem.php?id=2002
题意:考虑一种巧妙的分块:对于每个元素,维护跳出其所在块的步数以及跳出后到达的节点
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 222222
int n,m,a,block,k[stan],cnt,l[stan],r[stan],step[stan],to[stan],inn[stan],o,ans;
signed main(){
n=read();
block=sqrt(n);
for(int i=1;i<=n;++i)
k[i]=read();
cnt=n/block+((n%block)?1:0);
for(int i=1;i<=cnt;++i){
l[i]=(i-1)*block+1;
r[i]=i*block;
}
r[cnt]=n;
for(int i=1;i<=n;++i)
inn[i]=(i-1)/block+1;
for(int i=n;i;--i){
if(i+k[i]>n) step[i]=1;
if(inn[i]==inn[i+k[i]]){
step[i]=step[i+k[i]]+1;
to[i]=to[i+k[i]];
}else{
step[i]=1;
to[i]=i+k[i];
}
}
m=read();
for(int i=1;i<=m;++i){
o=read();
if(o==1){
a=read()+1;
ans=0;
while(1){
ans+=step[a];
if(!to[a]) break;
a=to[a];
}
write(ans);puts(" ");
}else{
a=read()+1;k[a]=read();
for(int i=a;i>=l[inn[a]];--i)
if(inn[i]==inn[i+k[i]]){
step[i]=step[i+k[i]]+1;
to[i]=to[i+k[i]];
}else{
step[i]=1;
to[i]=i+k[i];
}
}
}
return 0;
}
(4)单词背诵
题面见链接http://codevs.cn/problem/3013/
第一问瞎搞搞
第二问队列扫一遍就完了(摊手)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define hash 31
#define mod 100019
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 1111111
int n,tmp,vis[stan],si,m,ans,ans2,l,r,f[stan],in[stan],num[stan];
char word[stan][22],article[stan][22];
int get(char *x){
int len=strlen(x),ret=0;
for(int i=0;i1)){
if(in[tmp]) --num[tmp];
tmp=get(article[++l]);
}
ans2=min(ans2,r-l+1);
}
}
if(ans){
write(ans);
puts(" ");
write(ans2);
}else{
puts("0");
putchar('0');
}
return 0;
}
(5)玉蟾宫
我没权限...
也不知道哪里有...
黄学长博客有题面http://hzwer.com/1226.html
感慨一发,黄学长的伟大不在于他银牌或是PKU,而是在于他对于后人之学习有难以磨灭之贡献。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline long long read(){
long long i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 1111
char tmp[2];
int ans,n,m,map[stan][stan],stack[stan],lef[stan];
void solve(int h[]){
int top=0,len=0;
stack[top]=0;lef[top]=0;
for(int i=1;i<=m;++i){
if(h[i]>=stack[top]){
stack[++top]=h[i];
lef[top]=1;
}else{
len=0;
while(top&&stack[top]>h[i]){
len+=lef[top];
ans=max(ans,len*stack[top]);
--top;
}
stack[++top]=h[i];
lef[top]=len+1;
}
}
len=0;
while(top){
len+=lef[top];
ans=max(ans,len*stack[top]);
top--;
}
return ;
}
signed main(){
n=read();m=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
scanf("%s",tmp);
if(tmp[0]=='F')map[i][j]=map[i-1][j]+1;
}
for(int i=1;i<=n;++i) solve(map[i]);
write(ans*3);
return 0;
}
(6)幻想乡战略游戏(ZJOI2015)
今天写得最大的暴力
正解似乎是带权点分治
我选择分治预处理出分治树+树剖求LCA+特殊的小技巧
感谢lethalboy的分析,使我get到了这个神奇的技巧http://blog.csdn.net/qq_34564984/article/details/53791482
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 222222
int tot,nxt[stan*2],first[stan],goal[stan*2],dis[stan*2];
int dep[stan],sze[stan],fa[stan],son[stan],top[stan],vis[stan];
int root,total,maxsze[stan],p[stan];
int n,q,x,y,a,b,c;
long long to[stan],sum[stan],ans2[stan],ans1[stan];
int lastpos=1;
void addedge(int a,int b,int c){
++tot;nxt[tot]=first[a];first[a]=tot;goal[tot]=b;dis[tot]=c;
++tot;nxt[tot]=first[b];first[b]=tot;goal[tot]=a;dis[tot]=c;
return ;
}
void preact(){
static int que[stan];
int q=1;
que[q]=1;dep[q]=1;
for(int i=1;i<=q;++i){
int u=que[i];sze[u]=1;
for(int p=first[u];p;p=nxt[p])
if(goal[p]!=fa[u]){
fa[goal[p]]=u;
dep[goal[p]]=dep[u]+1;
to[goal[p]]=to[u]+dis[p];
que[++q]=goal[p];
}
}
for(int i=q;i>=2;--i){
int u=que[i];
sze[fa[u]]+=sze[u];
if(sze[u]>sze[son[fa[u]]])
son[fa[u]]=u;
}
for(int i=1;i<=q;++i){
int u=que[i];
if(top[u]) continue;
for(int v=u;v;v=son[v])
top[v]=u;
}
}
int lca(int u,int v){
int x=u,y=v;
while(top[u]!=top[v]){
if(dep[top[u]]dep[v]) swap(u,v);
return u;
}
void dfsroot(int u,int fa){
sze[u]=1;maxsze[u]=0;
for(int p=first[u];p;p=nxt[p])
if(goal[p]!=fa&&!vis[goal[p]]){
dfsroot(goal[p],u);
sze[u]+=sze[goal[p]];
if(sze[goal[p]]>maxsze[u])
maxsze[u]=sze[goal[p]];
}
if(total-sze[u]>maxsze[u]) maxsze[u]=total-sze[u];
if(maxsze[root]>maxsze[u]) root=u;
return ;
}
long long getdis(int x,int y){
int ori=lca(x,y);
return to[x]+to[y]-2*to[ori];
}
void solve(int u){
vis[u]=true;
for(int pa=first[u];pa;pa=nxt[pa])
if(!vis[goal[pa]]){
root=0;
total=maxsze[0]=sze[goal[pa]];
dfsroot(goal[pa],0);
p[root]=u;
solve(root);
}
return ;
}
long long calc(long long u){
long long ret=ans1[u];
for(int v=u;p[v];v=p[v]){
long long dist=getdis(p[v],u);
ret+=(ans1[p[v]]-ans2[v]);
ret+=dist*(sum[p[v]]-sum[v]);
}
return ret;
}
void update(int u,long long data){
sum[u]+=data;
for(int v=u;p[v];v=p[v]){
long long dist=getdis(p[v],u);
sum[p[v]]+=data;
ans1[p[v]]+=data*dist;
ans2[v]+=data*dist;
}
return ;
}
long long query(int u){
long long ret=calc(u);
for(int p=first[u];p;p=nxt[p]){
long long tmp=calc(goal[p]);
if(tmp
4.数学几何部
(1)FFT模板
不解释,http://uoj.ac/problem/34
写得巨丑无比
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline long long read(){
long long i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 1111111
complex poly1[stan],poly2[stan];
complex omega[stan],reomega[stan];
const double pi=acos(-1.0);
int nox,len,ans[stan*2],n,m;
inline void preact(int n1,int n2){
len=1;
while(len (cos(pi*i*2/len),sin(pi*i*2/len));
reomega[i]=conj(omega[i]);
}
return ;
}
inline void transform(complex *a,int len,complex *omega){
complex temp[stan];
for(int i=0;i>1;
for(int k=0;k t=a[k+j+m]*omega[len/l*j];
a[k+j+m]=a[k+j]-t;
a[k+j]+=t;
}
}
return ;
}
inline void dft(complex *a,int len){
transform(a,len,omega);
return ;
}
inline void idft(complex *a,int len){
transform(a,len,reomega);
for(int i=0;i
(2)仪仗队(SDOI2008)
题面见链接http://www.lydsy.com/JudgeOnline/problem.php?id=2190
根据简单易证法可得这是在求1-n的欧拉函数和的两倍加1
好像埃拉托色尼筛法也可以
但我选择线性
依然选择甩一个链接http://blog.csdn.net/nk_test/article/details/46242401
if(i%prime[j]==0)break;是线筛的灵魂
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline long long read(){
long long i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(long long x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 44444
int n,cnt,pri[stan],phi[stan];
long long ans;
bool exi[stan];
void linearsieve(int tot){
exi[1]=true;
phi[1]=1;
for(int i=2;i<=tot;++i){
if(!exi[i]){
pri[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&i*pri[j]<=tot;++j){
exi[i*pri[j]]=true;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*phi[pri[j]];
}
}
}
signed main(){
n=read();
linearsieve(n-1);
ans=1;
for(int i=1;i
又过了一天...调了一下午的战略计划...
少城的晚霞很美呢
赤华流光,衮衮如湔
希望我还能看到明天的太阳吧
Allalba Vincero.