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);
                 }
           }
     }
}
View Code

 

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);
}
View Code

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);
}
View Code

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;}
View Code

**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);
}
View Code

 

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);
}
View Code

 

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);

}
}
View Code

 

 

**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]);
}
View Code

 

以上是关于OI刷水记录的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3211 花神游历各国

bzoj3211: 花神游历各国(线段树)

BZOJ 3211 花神游历各国 线段树题解

BZOJ 3211: 花神游历各国

上帝造题的七分钟2 / 花神游历各国

BZOJ3211: 花神游历各国