A:简单题
每次判断向上转快,还是向下转快即可
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> using namespace std; #define N 10005 #define ll long long char s1[N] , s2[N]; int main() { // freopen("a.in" , "r" , stdin); int n; while(~scanf("%d" , &n)) { scanf("%s%s" , s1 , s2); int ans=0; for(int i=0 ; i<n ; i++){ int a=s1[i]-'0'; int b=s2[i]-'0'; if(a>b){ int t=a; a=b; b=t; } ans += min(b-a , 10+a-b); } printf("%d " , ans); } return 0; }
B:贪心
先判断所给的数中能否已经保证中位数大于y,不能的话,添加尽可能少的y使其满足中位数为y,剩下的值全定为1,判断总和是否超过x
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> using namespace std; #define N 10005 #define ll long long int n,k,p,x,y; int a[N]; int main() { // freopen("a.in" , "r" , stdin); int n; while(~scanf("%d%d%d%d%d" , &n,&k,&p,&x,&y)) { int pos = (n+1)/2; int cnt1 = 0 , cnt2=0; int sum=0; for(int i=1 ; i<=k ; i++){ scanf("%d" , &a[i]); if(a[i]>=y) cnt1++; else cnt2++; sum+=a[i]; } if(cnt1>n-pos){ for(int i=k+1 ; i<=n ; i++) a[i]=1,sum++; if(sum<=x){ for(int i=k+1 ; i<=n ; i++){ if(i<n) printf("%d " , a[i]); else printf("%d " , a[i]); } } else{ puts("-1"); } }else{ bool flag=true; if(pos-cnt1>n-k) flag=false; else{ int i; for(i=k+1 ; i<=k+pos-cnt1 ; i++){ a[i] = y; sum+=a[i]; } for(;i<=n;i++){ a[i]=1; sum+=a[i]; } if(sum>x) flag=false; } if(flag){ for(int i=k+1 ; i<=n ; i++){ if(i<n) printf("%d " , a[i]); else printf("%d " , a[i]); } } else puts("-1"); } } return 0; }
C:bfs
从起点bfs,判断能否有两条路径到达终点即可
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> using namespace std; #define N 1005 #define ll long long int n , m; int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}; struct Point{ int x,y; Point(int x=0 , int y=0):x(x),y(y){} }p[N][N]; int mat[N][N]; char s[N][N]; Point st , en; queue<Point> q; bool ok(int x , int y) { return x>0 && x<=n && y>0 && y<=m; } bool bfs() { while(!q.empty()) q.pop(); q.push(st); while(!q.empty()) { Point u = q.front(); q.pop(); for(int i=0 ; i<4 ; i++){ int xx = u.x+dir[i][0]; int yy = u.y+dir[i][1]; if(!ok(xx,yy)) continue; if(mat[xx][yy]==0){ mat[xx][yy]=-1; // cout<<"in: "<<u.x<<" "<<u.y<<" to: "<<xx<<" "<<yy<<endl; q.push(Point(xx,yy)); } else if(mat[xx][yy]==-1 && xx==en.x && yy==en.y){ // cout<<"in: "<<u.x<<" "<<u.y<<endl; return true; } } } return false; } int main() { // freopen("a.in" , "r" , stdin); while(~scanf("%d%d" , &n,&m)) { for(int i=1 ; i<=n ; i++) scanf("%s" , s[i]+1); for(int i=1 ; i<=n ; i++){ for(int j=1 ; j<=m ; j++){ if(s[i][j] == '.'){ mat[i][j]=0; } else mat[i][j]=-1; } } scanf("%d%d" , &st.x , &st.y); scanf("%d%d" , &en.x , &en.y); printf("%s " , bfs()?"YES":"NO"); } return 0; }
D:概率DP
dp[i][j][k] 表示剩余i个rock,j个siccsors,k个paper时的概率
初始dp[r][q][s]=1
状态转移
dp[i][j][k]+=dp[i+1][j][k]*(1.0*(i+1)*k/((i+1)*j+(i+1)*k+k*j));
dp[i][j][k]+=dp[i][j+1][k]*(1.0*(j+1)*i/(i*(j+1)+i*k+(j+1)*k));
dp[i][j][k]+=dp[i][j][k+1]*(1.0*(k+1)*j/(i*j+i*(k+1)+j*(k+1)));
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> using namespace std; #define N 210 #define ll long long double dp[N][N][N]; int r,s,q; void solve() { memset(dp,0,sizeof(dp)); dp[r][s][q]=1.0; for(int i=r ; i>=0 ; i--){ for(int j=s ; j>=0 ; j--){ for(int k=q ; k>=0 ; k--){ if(i==r && j==s && k==q) continue; dp[i][j][k] = 0; if(k) dp[i][j][k]+=dp[i+1][j][k]*(1.0*(i+1)*k/((i+1)*j+(i+1)*k+k*j)); if(i) dp[i][j][k]+=dp[i][j+1][k]*(1.0*(j+1)*i/(i*(j+1)+i*k+(j+1)*k)); if(j) dp[i][j][k]+=dp[i][j][k+1]*(1.0*(k+1)*j/(i*j+i*(k+1)+j*(k+1))); // cout<<i<<" "<<j<<" "<<k<<" "<<dp[i][j][k]<<endl; } } } } int main() { // freopen("a.in" , "r" , stdin); while(~scanf("%d%d%d" , &r,&s,&q)) { solve(); double ans1=0 , ans2=0 , ans3=0; for(int i=1 ; i<=r ; i++) ans1+=dp[i][0][0]; for(int i=1 ; i<=s ; i++) ans2+=dp[0][i][0]; for(int i=1 ; i<=q ; i++) ans3+=dp[0][0][i]; printf("%.11f %.11f %.11f " , ans1 , ans2 , ans3); } return 0; }
E:线段树
将点离散化后保存到线段树上,那么最多有200000个点
逐个添加,判断离散化的点之间可以形成多少对
在计算每个离散化的点和其他非离散化的区间内的点形成了多少对
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 200010 #define ls o<<1 #define rs o<<1|1 #define define_m int m=(l+r)>>1 #define ll long long int a[N*2] , k , p[N] , q[N] , val[N*2]; ll sum[N<<2]; ll ans=0; int getIndex(int key) { return lower_bound(a , a+k , key)-a; } void push_up(int o) { sum[o] = sum[ls]+sum[rs]; } void update(int o , int l , int r , int pos) { if(l==r && l==pos){ sum[o]++; return ; } define_m; if(m>=pos) update(ls , l , m , pos); else update(rs , m+1 , r , pos); push_up(o); } int query(int o , int l , int r , int s , int t) { if(l>r) return 0 ; if(l>=s && r<=t){ return sum[o]; } int ans=0; define_m; if(m>=s) ans+=query(ls , l , m , s , t); if(m<t) ans+=query(rs , m+1 , r , s , t); return ans; } int main() { // freopen("a.in" , "r" , stdin); int n; while(~scanf("%d" , &n)) { k=0; for(int i=0 ; i<n ; i++){ scanf("%d%d" , &p[i] , &q[i]); a[k++]=p[i] , a[k++]=q[i]; } sort(a , a+k); k = unique(a , a+k)-a; for(int i=0 ; i<n ; i++){ int index = getIndex(p[i]); val[index] = p[i]; p[i] = index; index = getIndex(q[i]); val[index] = q[i]; q[i]=index; } for(int i=0 ; i<n ; i++) swap(val[p[i]] , val[q[i]]); ans = 0; memset(sum , 0 , sizeof(sum)); for(int i=0 ; i<k ; i++){ int index = getIndex(val[i]); ans += (ll)query(1 , 0 , k-1 , index+1 , k-1); update(1 , 0 , k-1 , index); } //判断当前第i个点和所有非离散化区间能形成的匹配 for(int i=0 ; i<k ; i++){ ans += (ll)abs(val[i]-val[getIndex(val[i])]) - (ll)abs(i-getIndex(val[i])); } cout<<ans<<endl; } return 0; }