20160729noip模拟赛zld

image

首先显然有多少个奇数,就有多少个回文串是最优的(没有奇数时构造一个回文串

然后有了k个“核心”,把剩下的字符顺序安排到这些的两侧,最后最短的回文串长度就是答案

#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<complex>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;
#define inf 1001001001
#define infll 1001001001001001001LL
#define FOR(i,a,n) for(int (i)=a;(i)<=(n);++(i))
#define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i))
#define ll long long
#define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
#define gmax(a,b) (a)=max((a),(b))
#define gmin(a,b) (a)=min((a),(b))
#define ios0 ios_base::sync_with_stdio(0)
#define Ri register int
#define gc getchar()
#define il inline
il int read(){
    bool f=true;
    Ri x=0;char ch;
    while(!isdigit(ch=gc))if(ch=='-')f=false;
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=gc;}
    return f?x:-x;
}
#define gi read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
int n,a[100005];
int main(){
    FO(palindromic);
    int T=gi;
    while(T--){
        int cnt=0,sum=0;
        n=gi;    
        FOR1(i,n){
            a[i]=gi;sum+=a[i]; 
            if(a[i]&1)cnt++;
        }
//        printf("%d %d
",cnt,sum);
        if(cnt)
        cout<<(sum-cnt)/2/cnt*2+1<<endl; 
        else cout<<sum<<endl;
    } 
    return 0;
}

image

上次做这题:20160430ysy出题的时候

首先任意两点的最短路只有两种情况:曼哈顿距离,曼哈顿距离+2

那么我们考虑怎样的点对曼哈顿距离会被影响

显然是下面这样的:黑色是障碍,红色和蓝点距离加2

image

那么我们分行列统计这样的对数,就可以(

//fyb
//旅行 
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef double ll;
ll tot;
ll gg;
int n,m;
char s[2000];
int row[1010],col[1010];
int fyb(int i,int j,int k){return 2*(i-1)*(k-j);}
ll dorow(){
    ll ans=0;
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
            ans=ans+(m-(row[i]>0))*(m-(row[j]>0))*(j-i)/gg;
    for (int i=1;i<=n;i++)
        if (row[i]){
            ans=ans+fyb(row[i],row[i],m)/gg;
            for(int j=i-1;j>0&&row[j]&&row[j]<row[j+1];j--)    ans=ans + fyb(row[j],row[i],m)/gg;
            for(int j=i+1;j<=n&&row[j]&&row[j]<row[j-1];j++)ans=ans + fyb(row[j],row[i],m)/gg;                                                                
        }
    return ans;
}
ll docol(){
    ll ans=0;
    for (int i=1;i<m;i++)
        for (int j=i+1;j<=m;j++)
            ans=ans+(n-(col[i]>0))*(n-(col[j]>0))*(j-i)/gg;
    for (int i=1;i<=m;i++)
        if (col[i]){
            ans=ans+fyb(col[i],col[i],n)/gg;
            for(int j=i-1;j>0&&col[j]&&col[j]<col[j+1];j--) ans= ans + fyb(col[j],col[i],n)/gg;                                        
            for(int j=i+1;j<=m&&col[j]&&col[j]<col[j-1];j++) ans=ans + fyb(col[j],col[i],n)/gg;                                        
        }    
    return ans;
}
int main(){
    freopen("chess.in","r",stdin);
    freopen("chess.out","w",stdout); 
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        tot=0;memset(row,0,sizeof(row));memset(col,0,sizeof(col));
        for (int i=1;i<=n;i++){
            scanf("%s",s);
            for (int j=0;j<m;j++) 
                if (s[j]=='G'){
                    tot++;
                    row[i]=j+1;
                    col[j+1]=i;
                    break;
                }        
        }
        gg=n*m-tot;
        gg = gg * gg;
        double gg2 = dorow() + docol();
        gg2 = gg2 * 2.0;
        printf("%.4lf
", gg2);
    }
    return 0;
}

(出现了玄学的换行

image

设定ans[i][j]

表示当前时刻,从i-j最早什么时候到达

首先我们发现,加上一条边只会影响这条边的起点出发的边和到达终点的边

那么我们反向加边,每次更新一些ans[i][j]

查询就变得简洁很多了。

#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<complex>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;
#define inf 1001001001
#define infll 1001001001001001001LL
#define FOR0(i,n) for(int (i)=0;(i)<(n);++(i))
#define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i))
#define ll long long
#define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
#define gmax(a,b) (a)=max((a),(b))
#define gmin(a,b) (a)=min((a),(b))
#define ios0 ios_base::sync_with_stdio(0)
#define Ri register int
#define gc getchar()
#define il inline
il int read(){
    bool f=true;
    Ri x=0;char ch;
    while(!isdigit(ch=gc))if(ch=='-')f=false;
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=gc;}
    return f?x:-x;
}
#define gi read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
int n,m,q,u[233333],v[233333],ans[233333];
struct data{
    int a,b,c,d,id;
    void input(){
        a=gi;b=gi;c=gi;d=gi;
    }
}a[233333];
bool operator<(data a,data b){
    return a.a<b.a;
}
int dis[2333][2333];
int main(){
    FO(plan);
    n=gi;m=gi;q=gi;
    memset(dis,127/3,sizeof(dis));
    FOR1(i,n)    dis[i][i]=0;
    FOR1(i,m)    u[i]=gi,v[i]=gi;
    FOR1(i,q)    a[i].input(),a[i].id=i;
    sort(a+1,a+q+1);
    int t=q;
    for(int i=m;i>=1;i--){
        dis[u[i]][v[i]]=dis[v[i]][u[i]]=i;
        for(int j=1;j<=n;j++)    dis[u[i]][j]=min(dis[u[i]][j],max(dis[v[i]][j],i));
        for(int j=1;j<=n;j++)    dis[v[i]][j]=min(dis[v[i]][j],max(dis[u[i]][j],i));
        while(t&&a[t].a==i){
            if(dis[a[t].c][a[t].d]<=a[t].b)ans[a[t].id]=true;
            --t;
        }
    }
    for(int i=1;i<=q;i++) if(ans[i]) puts("Yes"); else puts("No");
}
原文地址:https://www.cnblogs.com/chouti/p/5729192.html