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;
}
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;
}
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;
}
当然,还有神仙操作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;
}