9.11模拟赛

T1.dinosaur

把(p[i],h[i])转换成一个区间[p[i]-h[i],p[i]+h[i]],考虑这些区间的关系

1.区间相离:单独计算每个区间长度/2,取最大值

2.区间包含:只计算大区间(实际操作中可以忽略,并入第一类)

3.区间相交:把两个区间合并,变成一个更大的区间

重载运算符不加const然后CE了,0分

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>

using namespace std;

typedef long long ll;

inline ll rd(){
    ll ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MAXN=300005;

typedef long long ll;

struct Node{
    ll l,r;
    bool operator <(const Node &rhs){
        return l==rhs.l?r<rhs.r:l<rhs.l;    
    }
}a[MAXN];

ll n;

int main(){
    freopen("dinosaur.in","r",stdin);
    freopen("dinosaur.out","w",stdout);
    n=rd();
    ll x,y;
    for(register int i=1;i<=n;i++){
        x=rd();y=rd();
        a[i].l = x-y;
        a[i].r = x+y;
    }
    sort(a+1,a+1+n);
    ll lstr=-1,lstl=-1;
    double ans=0.0;
    for(register int i=1;i<=n;i++){
        ll u=a[i].l,v=a[i].r;
        if(u<0) return puts("-1"),0;
        if(u>=lstr){
            ans=max(ans,1.0*(lstr-lstl)/2.0);
            lstl=u;lstr=v;
            continue;
        }
        lstr=max(lstr,v);
    }
    ans=max(ans,1.0*(lstr-lstl)/2);
    printf("%.1lf
",ans);
    return 0;
}
View Code

T2.inter

树剖维护一下即可

考完了才知道有个小剪枝,就是query_link时查到有值就可以返回了,线段树上query也是一样,因为我们只关心存不存在

#include<iostream>
#include<cstdlib>
#include<cstdio>

using namespace std;

const int MAXN=131072; 

inline int rd(){
  int ret=0,f=1;char c;
  while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
  while(isdigit(c))ret=ret*10+c-'0',c=getchar();
  return ret*f;
}

int n,m;

struct Edge{
  int next,to;
}e[MAXN<<1];
int ecnt=1,head[MAXN];
inline void adde(int x,int y){
  e[++ecnt].next = head[x];
  e[ecnt].to = y;
  head[x] = ecnt;
}

#define mid ((l+r)>>1)
#define ls (cur<<1)
#define rs (cur<<1|1)
int val[MAXN*4],add[MAXN*4];
inline void pushup(int cur){val[cur]=val[ls]+val[rs];}
inline void pushdown(int cur,int l,int r){
  add[ls]+=add[cur];
  add[rs]+=add[cur];
  val[ls]+=add[cur]*(mid-l+1);
  val[rs]+=add[cur]*(r-mid);
  add[cur]=0;
}
void build(int cur,int l,int r){
  if(l==r) {return;}
  build(ls,l,mid);
  build(rs,mid+1,r);
  pushup(cur);
}
int query(int L,int R,int cur,int l,int r){
  if(L<=l&&r<=R) return val[cur];
  pushdown(cur,l,r);
  int ret=0;
  if(L<=mid) ret+=query(L,R,ls,l,mid);
  if(ret) return 1;
  if(mid <R) ret+=query(L,R,rs,mid+1,r);
  return ret;
}
void update(int L,int  R,int  cur,int  l,int  r,int  w){
  if(L<=l&&r<=R){
    (add[cur]+=w);
    (val[cur]+=w*(r-l+1));
    return;
  }
  pushdown(cur,l,r);
  if(L<=mid) update(L,R,ls,l,mid,w);
  if(mid <R) update(L,R,rs,mid+1,r,w);
  pushup(cur);
}

int fa[MAXN],dep[MAXN],hs[MAXN],siz[MAXN];
void dfs1(int  cur,int  pre){
  fa[cur]=pre;dep[cur]=dep[pre]+1;siz[cur]=1;
  int mx=-1;
  for(register int i=head[cur];i;i=e[i].next){
    int v=e[i].to;
    if(v==pre) continue;
    dfs1(v,cur);
    siz[cur]+=siz[v];
    if(siz[v]>mx){mx=siz[v];hs[cur]=v;}
  }
}
int top[MAXN],id[MAXN],tim;
void dfs2(int cur,int tp){
  id[cur]=++tim;top[cur]=tp;
  if(hs[cur]) dfs2(hs[cur],tp);
  for(register int i=head[cur];i;i=e[i].next){
    int v=e[i].to;
    if(v==fa[cur]||v==hs[cur]) continue;
    dfs2(v,v);
  }
}
inline int query_link(int x,int y){
  int ret=0;
  while(top[x]!=top[y]){
    if(dep[top[x]]<dep[top[y]]) swap(x,y);
    ret+=query(id[top[x]],id[x],1,1,n);
    x=fa[top[x]];
    if(ret) return 1;
  }
  if(dep[x]>dep[y]) swap(x,y);
  ret+=query(id[x],id[y],1,1,n);
  return ret;
}
inline void update_link(int x,int y,int w){
  while(top[x]!=top[y]){
    if(dep[top[x]]<dep[top[y]]) swap(x,y);
    update(id[top[x]],id[x],1,1,n,w);
    x=fa[top[x]];
  }
  if(dep[x]>dep[y]) swap(x,y);
  update(id[x],id[y],1,1,n,w);
}

int main(){
  freopen("inter.in","r",stdin);
  freopen("inter.out","w",stdout);
  n=rd();
  register int x,y,u,v;
  for(register int i=1;i<=n-1;i++){
    x=rd();
    y=rd();
    adde(x,y);
    adde(y,x);
  }
  dfs1(1,0);
  dfs2(1,1);
  build(1,1,n);
  m=rd();
  for(register int i=1;i<=m;i++){
      x=rd();y=rd();u=rd();v=rd();
      update_link(x,y,1);
      if(query_link(u,v))puts("YES");
      else puts("NO");
      update_link(x,y,-1);
  }
  return 0;
}
View Code

T3.kenken

暴力大搜索,考场上经历了这么几个剪枝:

1.没有剪枝,甚至过不了第二个样例

2.记录联通块当前填了的数的积cur,若是cur*pow(联通块能填的最大的数,联通块未填的数个数)<联通块标的数,则剪枝

3.同2记录cur,若cur>连通块标的数,剪枝

到这里就有70分了,我也是这样交的,然而memcpy没有加cstring库,本地还能编译通过...CE

标答给了另一个角度的剪枝:

4.从标号小的联通块开始搜索,因为它们填写的方案比较少,若标号相同则从size小的开始搜索

//Stay foolish,stay hungry,stay young,stay simple
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector> 
using namespace std;

inline int rd(){
 int ret=0,f=1;char c;
 while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
 while(isdigit(c))ret=ret*10+c-'0',c=getchar();
 return ret*f;
}

const int MAXN=128;

int n;


int num[MAXN][MAXN];
int vaild[MAXN][MAXN];

vector<pair<int,int> > elm[MAXN];
int nxtx[MAXN],nxty[MAXN];

queue<int> Qx,Qy;
char bfsvis[MAXN][MAXN];
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
int scc,val[MAXN];//10*10
int bl[MAXN][MAXN],siz[MAXN];
inline void bfs(const int &sx,const int &sy,const int &id){
 Qx.push(sx);Qy.push(sy);int st=num[sx][sy];
 while(!Qx.empty()){
  int u=Qx.front(),v=Qy.front();
  Qx.pop();Qy.pop();
  if(bfsvis[u][v])continue;
  elm[id].push_back(make_pair(u,v)); 
//  cout<<"PUSH:"<<id<<" "<<u<<" "<<v<<endl;
  bl[u][v]=id;bfsvis[u][v]=1;
  siz[id]++;
  for(register int k=0;k<=3;k++){
   int x=u+dx[k],y=v+dy[k];
   if(x>n||y>n)continue;
   if(num[x][y]!=st)continue;
   if(bfsvis[x][y])continue;
   Qx.push(x);Qy.push(y);
  }
 }
}
int first_time;
int ans[MAXN][MAXN],sav[MAXN][MAXN];

int tmpval[MAXN];
int ans_num;
inline void check(){
 int flag=0;
 for(register int i=1;i<=n;i++){
  for(register int j=1;j<=n;j++){
   if(!flag){
    if(ans[i][j]>sav[i][j]){flag=2;break;}
    if(ans[i][j]<sav[i][j]){flag=1;break;}
   }
  }
 }
 ans_num++;
 if(flag==1) memcpy(sav,ans,sizeof(ans));
}

typedef long long ll;

char occx[MAXN][MAXN],occy[MAXN][MAXN];
ll sccmul[MAXN];
int sccres[MAXN]; 


inline ll qpow(ll x,ll y){
 ll ret=1ll;
 while(y){
  if(y&1)ret*=x;
  x*=x;
  y>>=1ll;
 }
 return ret;
}

void dfs(int dp){
 int x=nxtx[dp],y=nxty[dp];
 if(dp==n*n+1){
  if(!first_time){
   ans_num++;
   memcpy(sav,ans,sizeof(ans));
   first_time=1;
  }else check(); 
  return;
 }
 register int cur=bl[x][y],up=vaild[cur][0];
 if(sccmul[cur]>1ll*val[cur]){return;}
 if(1ll*sccmul[cur]*qpow(vaild[cur][up],siz[cur]-sccres[cur])<1ll*val[cur]){return;} 
 if(sccres[cur]==siz[cur]-1){
  int v=val[cur]/sccmul[cur];
  if(occx[x][v]||occy[y][v])return;
  occx[x][v]=1;occy[y][v]=1;
//  sccres[cur]++;sccmul[cur]*=v;
  ans[x][y]=v;
  dfs(dp+1);
//  sccres[cur]--;sccmul[cur]/=v;
  occx[x][v]=0;occy[y][v]=0;
 }else{ 
  for(register int i=1;i<=up;i++){
   int v=vaild[cur][i];
   if(occx[x][v]||occy[y][v])continue;
   ans[x][y]=v;
   occx[x][v]=1;occy[y][v]=1;
   sccres[cur]++;sccmul[cur]*=v;
   dfs(dp+1);
   sccres[cur]--;sccmul[cur]/=v;
   occx[x][v]=0;occy[y][v]=0;
  }
 }
}

int id[MAXN];
inline bool cmp(const int &x,const int &y){
// return siz[x]==siz[y]?val[x]<val[y]:siz[x]<siz[y]; 
 return val[x]==val[y]?siz[x]<siz[y]:val[x]<val[y];
}

int main(){
// freopen("kenken.in","r",stdin);
// freopen("kenken.out","w",stdout);
 n=rd();
 for(register int i=1;i<=n;i++){
  for(register int j=1;j<=n;j++){
   num[i][j]=rd();
  }
 }
 for(register int i=1;i<=n;i++){
  for(register int j=1;j<=n;j++){
   if(bfsvis[i][j])continue;
   bfs(i,j,++scc);val[scc]=num[i][j];
  }
 }
 int cc=0;
 for(register int i=1;i<=scc;i++){
  id[i]=i;
  for(register int j=1;j<=n;j++){
   if(val[i]%j)continue;
   vaild[i][++vaild[i][0]]=j;
  }
  sccmul[i]=1;
 }
 sort(id+1,id+1+scc,cmp);
 cc=0;
 for(int i=1;i<=scc;i++){
  int s=elm[id[i]].size();
  for(int j=0;j<s;j++){ 
   nxtx[++cc]=elm[id[i]][j].first;
   nxty[cc]=elm[id[i]][j].second;
  }
 }
// for(int i=1;i<=cc;i++){
//  cout<<nxtx[i]<<" "<<nxty[i]<<endl;
// } 
 dfs(1);
 printf("%d
",ans_num);
 if(ans_num==0) return 0;
 for(register int i=1;i<=n;i++){
  for(register int j=1;j<=n;j++){
   printf("%d ",sav[i][j]);
  }
  putchar('
');
 }
 return 0;
}
View Code

当然,还有神仙操作Dancing Links X,吊打搜索

#include<bits/stdc++.h>
using namespace std; 
const int N=11,M=510;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
struct node2{ int c[N][N]; } ans[M];
bool operator< (node2 x,node2 y){
    for(int i = 1; i < N; i++)
        for(int j = 1; j<N; j++)
            if(x.c[i][j] != y.c[i][j])
                return x.c[i][j] < y.c[i][j];
    return 0;
}
struct node{ int x, y; };

vector<node> b[N * N];
vector<int> p[N * N]; 
int a[N][N], c[N][N], h[N][N], h1[N][N], h2[N][N];
int n, cnt = 0, tot = 0;

int read() {
    int x = 0, f = 1;
    char c = 0;
    for (; !isdigit(c); c=getchar()) if(c == '-') f = -1;
    for (; isdigit(c); c=getchar()) x = x * 10 + c - 48;
    return x * f;
}
int factor(int x) {
    int t = 0;
    for (int i = 1; i * i <= x; i++)
        t += (int)(x % i == 0);
    return t;
}
bool cmp(vector<node> x, vector<node> y) {
    if (x.size() == y.size())
        return factor(x[0].x) <= factor(y[0].x);
    return x.size() < y.size();
}
void divide(int t, int x){
    for (int i = 1; i <= n; i++)
        if (x % i == 0) p[t].push_back(i);
}
void dfs(int x, int y) {
    h[x][y] = 1;
    b[cnt].push_back((node){ x, y });
    for (int i = 0; i < 4; i++) {
        int tx = x + dx[i];
        int ty = y + dy[i];
        if (tx > 0 && tx <= n && ty > 0 && 
            ty <= n && !h[tx][ty] &&
            a[tx][ty] == a[x][y])
            dfs(tx, ty);
    }
}
void work(int dep);
void fillp(int t, int dep, int s, int tot) {
    if (dep > tot) work(t + 1);
    else {
        int x=b[t][dep].x, y = b[t][dep].y;
        for (int i = 0; i < p[t].size(); i++) {
            int u=p[t][i];
            if ((s == u || dep < tot) && s % u == 0 &&
                !h1[x][u] && !h2[y][u]){
                h1[x][u] = 1;
                h2[y][u] = 1;
                c[x][y] = u;
                fillp(t, dep + 1, s / u, tot);
                c[x][y] = 0;
                h1[x][u] = 0;
                h2[y][u]=0;
            }
        }
    }
}
void work(int dep) {
    if (dep > cnt) {
        tot++;
        for (int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                ans[tot].c[i][j] = c[i][j];
    } else {
        int num=b[dep][0].x;
        int tot=b[dep].size() - 1;
        fillp(dep, 1, num, tot);
    }
}
int main() {
//    freopen("kenken.in", "r", stdin);
//    freopen("kenken.out", "w", stdout); 
    n = read();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            a[i][j] = read();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (!h[i][j]) {
                cnt++;
                b[cnt].push_back((node){ a[i][j], 0 });
                dfs(i, j);
            }
    sort(b + 1, b + cnt + 1, cmp);
    for (int i = 1; i <= cnt; i++)
        divide(i, b[i][0].x);
    work(1);
    cout << tot << "
";
    node2 t = ans[1];
    for (int i = 2; i <= tot; i++)
        t = min(t, ans[i]);
    for (int i = 1;i <= n; i++){
        for (int j = 1; j < n; j++)
            cout << t.c[i][j] << " ";
        cout << t.c[i][n] << "
";
    }
    return 0;
}
未经许可,禁止搬运。
原文地址:https://www.cnblogs.com/ghostcai/p/9630149.html