OI刷水记录
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OI刷水记录相关的知识,希望对你有一定的参考价值。
3.19
颓了一周:
**3211: 花神游历各国
区间开方区间查询 可以用树状数组暴力修改+并查集维护下一个不为1的数
#include<bits/stdc++.h> #define rep(i,l,r) for(int i=l;i<=r;i++) #define N 101333 typedef long long ll; int f[N],a[N],now,m,n,l,r,x,delta; ll c[N]; inline void add(int x,int k){while(x<=n) c[x]+=k,x+=x&-x;} inline ll ask(int x){ll tot=0;while(x) tot+=(ll)c[x],x-=x&-x;return tot;} inline int find(int x){if(f[x]==x) return x;else return f[x]=find(f[x]);} inline int read(){int x=0,ch=getchar();while(ch<‘0‘||ch>‘9‘) ch=getchar();while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-48,ch=getchar();return x;} int main () { scanf("%d",&n); rep(i,1,n) a[i]=read(),add(i,a[i]),f[i]=i+(a[i]<=1); f[n+1]=n+1; scanf("%d",&m); while(m--) { x=read(); l=read(); r=read(); if(x==1) printf("%lld\n",ask(r)-ask(l-1)); else { for(l=find(l);l<=r;l=find(l+1)) { int delta=floor(sqrt(a[l])); add(l,delta-a[l]); a[l]=delta; if(a[l]<=1) f[l]=find(l+1); } } } }
1789: [Ahoi2008]Necklace Y型项链
暴力枚举前缀串判定
#include<bits/stdc++.h> #define N 60 #define rep(i,l,r) for(i=l;i<=r;i++) using namespace std; int s[N],ans,tot,a,b,c; char s1[N],s2[N],s3[N]; inline int cal(int x) { int tot=0,i; rep(i,1,min(x,a)) if(s1[i]!=s[i]) break; tot+=x-i+1+a-i+1; rep(i,1,min(x,b)) if(s2[i]!=s[i]) break; tot+=x-i+1+b-i+1; rep(i,1,min(x,c)) if(s3[i]!=s[i]) break; tot+=x-i+1+c-i+1; return tot; } int main () { scanf("%d%s",&a,s1+1); scanf("%d%s",&b,s2+1); scanf("%d%s",&c,s3+1); ans=a+b+c; int i; rep(i,1,a) { s[++tot]=s1[i]; ans=min(ans,cal(tot)); } memset(s,0,sizeof(s)); tot=0; rep(i,1,b) { s[++tot]=s2[i]; ans=min(ans,cal(tot)); } memset(s,0,sizeof(s)); tot=0; rep(i,1,c) { s[++tot]=s3[i]; ans=min(ans,cal(tot)); } printf("%d",ans); }
1008: [HNOI2008]越狱
组合数学水题。。
#include<bits/stdc++.h> #define czl 100003 using namespace std; typedef long long ll; ll m,n; ll power(ll x,ll k) { if(!k) return 1; ll t=power(x,k/2)%czl; if(k%2==0) return t*t%czl;else return t*t*x%czl; } int main () { scanf("%lld%lld",&m,&n); ll ans=power(m,n)%czl + czl - m*power(m-1,n-1)%czl; printf("%lld",ans%czl); }
1192: [HNOI2006]鬼谷子的钱袋
水。
#include<iostream> #include<cstdio> using namespace std; int main(){int n,i;cin>>n;for(i=1;(1<<i)<n;i++);cout<<i;}
**1040: [ZJOI2008]骑士
基环森林上DP。基环树就是在树上加上一条边。
这题可以对于每一棵环套树,先dfs找环,找到环以后断环为链并将断开的两个点强制其中一个点为根且不选做一次树形DP,对另一个点做同样操作。 //by hzwer
#include<bits/stdc++.h> #define N 1023333 #define rep(i,l,r) for(int i=l;i<=r;i++) using namespace std; int tot=1,head[N],u,v,E,s[N],n,x; long long ans,anss,f[N][2]; bool vis[N]; struct node{ int to,next; }e[N<<2]; inline void ins(int u,int v) { e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; } inline int read() { int x=0,ch=getchar(); while(ch<‘0‘ || ch>‘9‘) ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return x; } void dfs(int x,int pre) { vis[x]=1; for(int k=head[x];k;k=e[k].next) { if(e[k].to==pre) continue; if(vis[e[k].to]) { u=x; v=e[k].to; E=k; continue; } dfs(e[k].to,x); } } void trdp(int x,int pre) { f[x][1]=s[x]; f[x][0]=0; for(int k=head[x];k;k=e[k].next) { if(k==E || (k^1)==E || e[k].to==pre) continue; trdp(e[k].to,x); f[x][1]+=f[e[k].to][0]; f[x][0]+=max(f[e[k].to][1],f[e[k].to][0]); } } int main () { scanf("%d",&n); rep(i,1,n) { s[i]=read(); x=read(); ins(i,x); ins(x,i); } rep(i,1,n) if(!vis[i]) { dfs(i,0); trdp(u,0); ans=f[u][0]; trdp(v,0); ans=max(ans,f[v][0]); anss+=ans; } printf("%lld",anss); }
1877: [SDOI2009]晨跑
费用流水题。
#include<bits/stdc++.h> #define rep(i,l,r) for(int i=l;i<=r;i++) #define inf 2147483647 #define N 500 using namespace std; struct Edge{ int to,next,from,c,w; }e[50000]; int head[N],tot=1,ans,dis[N],from[N],i,n,p,T,num[N][2],sum,m,a,b,c; bool used[N]; inline void ins(int u,int v,int w,int cost) { e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w; e[tot].c=cost; e[tot].from=u; } inline int left(int x) { return num[x][0]; } inline int right(int x) { return num[x][1]; } inline bool spfa() { queue<int> q; for(int i=0;i<=T;i++) dis[i]=inf; dis[1]=0; q.push(1); used[1]=1; while(!q.empty()) { int x=q.front(); q.pop(); for(int k=head[x];k;k=e[k].next) if(e[k].w>0&&dis[x]+e[k].c<dis[e[k].to]){ dis[e[k].to]=dis[x]+e[k].c; from[e[k].to]=k; if(!used[e[k].to]) { used[e[k].to]=1; q.push(e[k].to); } } used[x]=0; } if(dis[T]==inf) return 0;else return 1; } inline void run() { int x=inf; for(int k=from[T];k;k=from[e[k].from]) x=min(x,e[k].w); for(int k=from[T];k;k=from[e[k].from]) { e[k].w-=x; e[k^1].w+=x; ans+=e[k].c*x; } } inline int read() { int x=0; char ch=getchar(); while(ch<‘0‘ || ch>‘9‘) ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return x; } inline void insert(int u,int v,int w,int c) { ins(u,v,w,c); ins(v,u,0,-c); } int main () { scanf("%d%d",&n,&m); rep(i,1,n) num[i][0]=++sum,num[i][1]=++sum; insert(left(1),right(1),inf,0); insert(left(n),right(n),inf,0); rep(i,2,n-1) insert(left(i),right(i),1,0); T=right(n); while(m--) { a=read(); b=read(); c=read(); insert(right(a),left(b),1,c); } while(spfa()) run(); printf("%d %d",e[2^1].w,ans); }
1876: [SDOI2009]SuperGCD
用抄的java水过了。。
import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner cin=new Scanner(System.in); BigInteger a=null,b=null,c=null; a=cin.nextBigInteger(); b=cin.nextBigInteger(); c=a.gcd(b); System.out.println(c); } }
**1878: [SDOI2009]HH的项链
询问区间内出现了多少个不同的数。首先这题可以离线,按询问左端点排序。首先把每个数第一次出现的位置加一,然后从左到右扫:判断一下如果当前的点是某个询问的左端点时 输出1~询问右端点的前缀和 最后把当前点-1 下一个出现相同数的点加一 用树状数组维护即可。
#include<bits/stdc++.h> #define N 202333 #define rep(i,l,r) for(int i=l;i<=r;i++) using namespace std; int c[N],s[N],m,now,n,head[1023333],next[1023333],ans[N]; struct node{ int l,r,num; }a[N]; bool cmp(node a,node b) { return a.l<b.l; } inline int ask(int x) { int tot=0; while(x) { tot+=c[x]; x-=x&-x; } return tot; } inline void update(int x,int k) { while(x<=n) { c[x]+=k; x+=x&-x; } } inline int read() { int x=0,ch=getchar(); while(ch<‘0‘||ch>‘9‘) ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); return x; } int main () { scanf("%d",&n); rep(i,1,n) s[i]=read(); for(int i=n;i;i--) next[i]=head[s[i]],head[s[i]]=i; scanf("%d",&m); rep(i,1,m) a[i].l=read(),a[i].r=read(),a[i].num=i; rep(i,0,1000000) if(head[i]) update(head[i],1); sort(a+1,a+1+m,cmp); now=1; rep(i,1,n) { while(now<=m && a[now].l==i) { ans[a[now].num]=ask(a[now].r); ++now; } update(i,-1); if(next[i])update(next[i],1); } rep(i,1,m) printf("%d\n",ans[i]); }
以上是关于OI刷水记录的主要内容,如果未能解决你的问题,请参考以下文章