前记:
第一次打cc感觉要自爆啊。
(不过似乎题目非常良心啊,似乎没有撕烤题啊)
第一个最小值的位置。
#include
#define gc getchar()
using namespace std;
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
int main()
{
int T=read();
while (T--)
{
int n=read();
int Min=1000000,pos=0;
for (int i=1;i<=n;i++)
{
int x=read();
if (xx,pos=i;
}
printf("%d\n",pos);
}
return 0;
}
字典序最小错排。
#include
#define gc getchar()
using namespace std;
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
int main()
{
int T=read();
while (T--)
{
int n=read();
if (n&1)
{
for (int i=1;2*i1;i++)
printf("%d %d ",2*i,2*i-1);
printf("%d %d %d\n",n-1,n,n-2);
}
else
{
for (int i=1;2*i<=n;i++)
printf("%d %d%s",2*i,2*i-1,i==(n/2)?"\n":" ");
}
}
return 0;
}
字符串中的数字能组成哪些大写字母的ascll码
#include
#define gc getchar()
#define N 100009
using namespace std;
int number[10];
char str[N];
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
int main()
{
int T=read();
while (T--)
{
scanf("%s",str+1);
int len=strlen(str+1);
memset(number,0,sizeof(number));
for (int i=1;i<=len;i++)
number[str[i]-'0']++;
for (int i=65;i<=90;i++)
{
if (i/10!=i%10)
{
if (number[i/10]&&number[i%10]) putchar(i);
}
else
{
if (number[i/10]>1) putchar(i);
}
}
puts("");
}
return 0;
}
有两种操作:
1、对 [l,r] [ l , r ] 的区间加上 a a
2、对 [l,r] [ l , r ] 区间的操作再做一遍
问最后每个数的值。
因为可以离线,所以倒着跑。
如果是操作2,差分操作区间,如果是操作1,差分 a a 乘上当前操作的累计次数。
#include
#define gc getchar()
#define ll long long
#define N 100009
#define mod 1000000007
using namespace std;
int n,m,tg[N],add[N];
struct Qry
{
int op,l,r;
}p[N];
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
int main()
{
int T=read();
while (T--)
{
n=read(),m=read();
for (int i=1;i<=m;i++)
p[i].op=read(),p[i].l=read(),p[i].r=read();
memset(tg,0,sizeof(tg));
memset(add,0,sizeof(add));
tg[m]=1;
for (int i=m;i;i--)
{
tg[i]=(tg[i]+tg[i+1])%mod;
if (p[i].op==1)
{
add[p[i].l]=(add[p[i].l]+tg[i])%mod;
add[p[i].r+1]=(add[p[i].r+1]+mod-tg[i])%mod;
}
else
{
tg[p[i].r]=(tg[p[i].r]+tg[i])%mod;
tg[p[i].l-1]=(tg[p[i].l-1]+mod-tg[i])%mod;
}
}
int sum=0;
for (int i=1;i<=n;i++)
{
sum=(sum+add[i])%mod;
printf("%d%s",sum,i==n?"\n":" ");
}
}
return 0;
}
每个点拆成两个跑并查集就好。
#include
#define gc getchar()
#define N 200009
using namespace std;
int fa[N],n,m;
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
int xx=find(x),yy=find(y);
if (xx!=yy) fa[xx]=yy;
}
int main()
{
int T=read();
while (T--)
{
n=read(),m=read();
for (int i=1;i<=n*2;i++) fa[i]=i;
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
if (z==1)
{
merge(x,y+n);
merge(y,x+n);
}
else
{
merge(x,y);
merge(x+n,y+n);
}
}
bool flag=1;
for (int i=1;i<=n;i++)
if (find(i)==find(i+n))
{
flag=0;
break;
}
puts(flag?"yes":"no");
}
return 0;
}
一个点对于根的贡献只取决于它的深度和当前天数。
显然可以每个深度一起处理。
然后会发现关系大概是个组合数(深度标准不同,写出来也不同)
之后就可以Lucas定理套用了。
算答案时需要求出形如某几位必须为0,剩余几位任意都可的 val v a l 异或和,这个只要子集dp就可以了。
#include
#define gc getchar()
#define ll long long
#define N 200009
#define mod 1000000007
using namespace std;
int n,Q,x,y,number,first[N],deep[N],fa[N],bin[20];
ll val[N],dp[N<<1],v[N<<1];
struct edge
{
int to,next;
void add(int x,int y)
{
to=y,next=first[x],first[x]=number;
}
}e[N<<1];
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
ll Read()
{
ll x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
ll s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10ll+ch-48;
return s*x;
}
void dfs(int x)
{
deep[x]=deep[fa[x]]+1;
v[deep[x]]^=val[x];
for (int i=first[x];i;i=e[i].next)
if (e[i].to!=fa[x]) fa[e[i].to]=x,dfs(e[i].to);
}
int main()
{
bin[0]=1;
for (int i=1;i<20;i++) bin[i]=bin[i-1]<<1;
n=read(),Q=read();
for (int i=1;ix=read()+1,y=read()+1;
e[++number].add(x,y),e[++number].add(y,x);
}
for (int i=1;i<=n;i++) val[i]=Read();
deep[0]=-1;
dfs(1);
for (int i=0;i18];i++)
{
dp[i]=v[0];
for (int j=i;j;j=(j-1)&i) dp[i]^=v[j];
}
while (Q--)
{
ll x=Read()-1;
if (x==-1)
{
printf("%lld\n",val[1]);
continue;
}
int pos=0;
for (int i=0;i<18;i++,x>>=1)
if (!(x&1)) pos+=bin[i];
printf("%lld\n",dp[pos]);
}
return 0;
}
这题真的非常有毒。。。
直接考虑 k=3 k = 3 ,发现需要枚举各种三条边之间的关系。
其中有几种非常好算,其中有一种是三元环,这个枚举一条边,在枚举它度数较小的顶点,用map判,这样可以显然证明是 O(mm−−√logm) O ( m m l o g m ) 的。有一些直接算比较难的,可以通过好算的和三元环的情况容斥得到。
#include
#define gc getchar()
#define ll long long
#define N 100009
#define mod 1000000007
#define pii pair
using namespace std;
int n,m,first[N],number,ans,bin[N<<1],k,delta,d[N],sum,num,Num;
const int sed=195337;
struct hash
{
#define mo 100007
#define M 5000010
int head[mo],dh[mo];
int x[M],y[M],next[M],siz,cnt;
inline void clear()
{
++cnt,siz=0;
}
void ins(int _x,int _y)
{
int s=(1LL*_x*sed+_y)%mo;
if (dh[s]!=cnt) dh[s]=cnt,head[s]=0;
next[++siz]=head[s],head[s]=siz;
x[siz]=_x,y[siz]=_y;
}
int count(int _x,int _y)
{
int s=(1LL*_x*sed+_y)%mo;
if (dh[s]!=cnt) return 0;
for (s=head[s];s;s=next[s])
if (x[s]==_x&&y[s]==_y) return 1;
return 0;
}
}pos;
struct Edge
{
int x,y;
}E[N];
struct edge
{
int to,next;
void add(int x,int y)
{
to=y,next=first[x],first[x]=number;
}
}e[N<<1];
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
int work()
{
int ret=0;
for (int i=1;i<=m;i++)
for (int j=first[E[i].x];j;j=e[j].next)
if (pos.count(E[i].y,e[j].to)) ret++;
ret/=3;
return ret;
}
int main()
{
bin[0]=1;
for (int i=1;i<(N<<1);i++) bin[i]=(bin[i-1]<<1)%mod;
int T=read();
while (T--)
{
pos.clear();
n=read(),m=read(),k=read();
number=0;
for (int i=1;i<=n;i++) first[i]=d[i]=0;
for (int i=1;i<=m;i++)
{
int x=read(),y=read();
E[i].x=x,E[i].y=y;
e[++number].add(x,y);
e[++number].add(y,x);
d[x]++,d[y]++;
pos.ins(x,y);
pos.ins(y,x);
}
for (int i=1;i<=m;i++)
if (d[E[i].x]>d[E[i].y]) swap(E[i].x,E[i].y);
if (k==1)
{
ans=(ll)m*bin[n-2]%mod;
printf("%d\n",ans);
continue;
}
if (k==2)
{
ans=(ll)m*bin[n-2]%mod;
for (int i=1;i<=m;i++)
ans=(ans+(ll)(m-d[E[i].x]-d[E[i].y]+1)*bin[n-4]%mod)%mod;
for (int i=1;i<=m;i++)
ans=(ans+(ll)(d[E[i].x]-1)*bin[n-3]%mod)%mod;
for (int i=1;i<=m;i++)
ans=(ans+(ll)(d[E[i].y]-1)*bin[n-3]%mod)%mod;
printf("%d\n",ans);
continue;
}
if (k==3)
{
ans=(ll)m*bin[n-2]%mod;
for (int i=1;i<=m;i++)
ans=(ans+(ll)3*(m-d[E[i].x]-d[E[i].y]+1)*bin[n-4]%mod)%mod;
for (int i=1;i<=m;i++)
ans=(ans+(ll)3*(d[E[i].x]-1)*bin[n-3]%mod)%mod;
for (int i=1;i<=m;i++)
ans=(ans+(ll)3*(d[E[i].y]-1)*bin[n-3]%mod)%mod;
num=work();
Num=0;
for (int i=1;i<=n;i++)
if (d[i]>=2) Num=(Num+(ll)d[i]*(d[i]-1)/2*(m-d[i])%mod)%mod;
for (int i=1;i<=m;i++)
Num=(Num-(ll)2*(d[E[i].x]-1)*(d[E[i].y]-1)%mod+mod)%mod;
Num=(Num+3*num)%mod;
for (int i=1;i<=n;i++)
if (d[i]>=3) ans=(ans+(ll)d[i]*(d[i]-1)%mod*(d[i]-2)%mod*bin[n-4]%mod)%mod;
for (int i=1;i<=m;i++)
if (n>=4) ans=(ans+(ll)6*(d[E[i].x]-1)*(d[E[i].y]-1)%mod*bin[n-4]%mod)%mod;
sum=(ll)m*(m-1)*(m-2)/6%mod;
for (int i=1;i<=n;i++)
if (d[i]>=3) sum=(sum-(ll)d[i]*(d[i]-1)*(d[i]-2)/6%mod+mod)%mod;
sum=(sum-Num+mod)%mod;
for (int i=1;i<=m;i++)
sum=(sum-(ll)(d[E[i].x]-1)*(d[E[i].y]-1)%mod+mod)%mod;
sum=(sum+2*num)%mod;
if (n>=6) ans=(ans+(ll)6*sum*bin[n-6]%mod)%mod;
if (n>=5) ans=(ans+(ll)6*Num*bin[n-5]%mod)%mod;
ans=(ans-(ll)6*num*bin[n-4]%mod+mod)%mod;
printf("%d\n",ans);
continue;
}
}
return 0;
}
这题在猫大指导下我先想了一个 O(kn2) O ( k n 2 ) 的dp。
先不妨假设高度递减, dp[i][j] d p [ i ] [ j ] 表示进行了 i i 次高度变化,且最后一次的阶梯高度为 h[j] h [ j ] 的到 j j 的最大面积。
然后我开始想优化,经梁大大一句话提醒,发现似乎这 dp d p 有点单调性。我们发现 j j 决策点的高度是递减的。
画了一下图,发现似乎可以cdq分治后用单调栈维护。
然后我愉快地开始敲优化,然后愉快地发现我得到了70分(wtf??)。这TM还能错小数据点??然后我就强加了 O(kn2) O ( k n 2 ) 强行过了中间30分。(所以程序到底还有什么bug啊??)
#include
#define gc getchar()
#define mid (l+r>>1)
#define ll long long
#define ld long double
#define N 100009
#define inf 1e19
using namespace std;
int n,k,m,lg[N],bit[20],q[N],now,last;
vector Q;
ll dp[2][N],a[N],Min[N][20],B[N],pos[N];
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
int get(int l,int r)
{
int k=lg[r-l+1];
return min(Min[l][k],Min[r-bit[k]+1][k]);
}
ll A(int i)
{
return dp[last][i]+B[i];
}
ld get_k(int j,int k)
{
if (pos[j]==pos[k]) return (ld)(A(j)return (ld)(A(j)-A(k))/(pos[j]-pos[k]);
}
bool check(int x,int y,int z)
{
return (A(x)-A(y))*(pos[y]-pos[z])>=(A(y)-A(z))*(pos[x]-pos[y]);
}
void solve(int l,int r)
{
if (l==r) return;
solve(l,mid);
int Min=N;
int head=1,tail=0,p=mid;
for (int i=mid+1;i<=r;i++)
if (a[i]while (p>=l&&a[p]>a[i])
{
//ins(p);
while (tail>head&&check(q[tail-1],q[tail],p)/*get_k(q[tail-1],q[tail])>=get_k(q[tail],p)*/) tail--;
q[++tail]=p;
p--;
}
while (tail>head&&a[i]*(pos[q[tail-1]]-pos[q[tail]])<=A(q[tail-1])-A(q[tail]))
tail--;
if (tail>=head) dp[now][i]=max(dp[now][i],A(q[tail])+(ll)(i-pos[q[tail]]+1)*a[i]);
}
solve(mid+1,r);
}
int main()
{
lg[0]=-1;
for (int i=1;i>1]+1;
bit[0]=1;
for (int i=1;i<20;i++) bit[i]=bit[i-1]<<1;
int T=read();
while (T--)
{
ll Ans=0;
n=read(),k=read();
if (n<=1500)
{
Q.clear();
for (int i=1;i<=n;i++) a[i]=read(),Q.push_back(a[i]);
sort(Q.begin(),Q.end());
unique(Q.begin(),Q.end());
for (int i=1;i<=n;i++)
a[i]=lower_bound(Q.begin(),Q.end(),a[i])-Q.begin();
for (int i=1;i<=n;i++) Min[i][0]=a[i];
for (int i=1;bit[i]<=n;i++)
for (int j=1;j+bit[i]-1<=n;j++)
Min[j][i]=min(Min[j][i-1],Min[j+bit[i-1]][i-1]);
int now=0,last=1;
memset(dp[now],0,sizeof(dp[now]));
for (int i=1;i<=n;i++)
for (int j=1;j<=i;j++)
{
if (get(j,i)==a[i])
dp[now][i]=max(dp[now][i],(ll)Q[a[i]]*(i-j+1));
Ans=max(Ans,(ll)Q[get(j,i)]*(i-j+1));
}
for (int i=1;i<=k;i++)
{
last=now,now^=1;
memset(dp[now],0,sizeof(dp[now]));
for (int j=1;jint pos=0;
for (int r=j+1;r<=n;r++)
if (a[r]if (!pos) pos=r;
if (get(pos,r)==a[r]) dp[now][r]=max(dp[now][r],dp[last][j]+Q[a[j]]*(pos-j-1)+Q[get(pos,r)]*(r-pos+1));
}
}
for (int j=1;j<=n;j++)
{
int pos=j+1;
ll now_ans=dp[now][j];
while (pos<=n&&a[pos]>=a[j]) now_ans+=Q[a[j]],pos++;
Ans=max(Ans,now_ans);
}
}
for (int i=1;i*2<=n;i++) swap(a[i],a[n-i+1]);
for (int i=1;i<=n;i++) Min[i][0]=a[i];
for (int i=1;bit[i]<=n;i++)
for (int j=1;j+bit[i]-1<=n;j++)
Min[j][i]=min(Min[j][i-1],Min[j+bit[i-1]][i-1]);
now=0,last=1;
memset(dp[now],0,sizeof(dp[now]));
for (int i=1;i<=n;i++)
for (int j=1;j<=i;j++)
{
if (get(j,i)==a[i])
dp[now][i]=max(dp[now][i],(ll)Q[a[i]]*(i-j+1));
Ans=max(Ans,(ll)Q[get(j,i)]*(i-j+1));
}
for (int i=1;i<=k;i++)
{
last=now,now^=1;
memset(dp[now],0,sizeof(dp[now]));
for (int j=1;jint pos=0;
for (int r=j+1;r<=n;r++)
if (a[r]if (!pos) pos=r;
if (get(pos,r)==a[r]) dp[now][r]=max(dp[now][r],dp[last][j]+Q[a[j]]*(pos-j-1)+Q[get(pos,r)]*(r-pos+1));
}
}
for (int j=1;j<=n;j++)
{
int pos=j+1;
ll now_ans=dp[now][j];
while (pos<=n&&a[pos]>=a[j]) now_ans+=Q[a[j]],pos++;
Ans=max(Ans,now_ans);
}
}
printf("%lld\n",Ans);
continue;
}
for (int i=1;i<=n;i++) a[i]=read();
a[n+1]=0;
for (int i=1;i<=n+1;i++) Min[i][0]=a[i];
for (int i=1;bit[i]<=n+1;i++)
for (int j=1;j+bit[i]-1<=n+1;j++)
Min[j][i]=min(Min[j][i-1],Min[j+bit[i-1]][i-1]);
for (int i=1;i<=n;i++)
{
int l=i,r=n+1,ret=i;
while (l<=r)
{
if (get(i,mid)==a[i]) l=mid+1;
else ret=mid,r=mid-1;
}
pos[i]=ret;
}
now=1,last=0;
for (int i=1;i<=n;i++)
{
int l=1,r=i,ret=i;
while (l<=r)
{
if (get(mid,i)==a[i]) ret=mid,r=mid-1;
else l=mid+1;
}
dp[now][i]=(ll)a[i]*(i-ret+1);
Ans=max(Ans,dp[now][i]+(ll)(pos[i]-i-1)*a[i]);
B[i]=(ll)a[i]*(pos[i]-i-1);
}
for (int i=1;i<=k;i++)
{
last=now,now^=1;
memset(dp[now],0,sizeof(dp[now]));
solve(1,n);
for (int j=1;j<=n;j++)
Ans=max(Ans,dp[now][j]+B[j]);
}
for (int i=1;i*2<=n;i++) swap(a[i],a[n-i+1]);
for (int i=1;i<=n+1;i++) Min[i][0]=a[i];
for (int i=1;bit[i]<=n+1;i++)
for (int j=1;j+bit[i]-1<=n+1;j++)
Min[j][i]=min(Min[j][i-1],Min[j+bit[i-1]][i-1]);
for (int i=1;i<=n;i++)
{
int l=i,r=n+1,ret=i;
while (l<=r)
{
if (get(i,mid)==a[i]) l=mid+1;
else ret=mid,r=mid-1;
}
pos[i]=ret;
}
now=1,last=0;
for (int i=1;i<=n;i++)
{
int l=1,r=i,ret=i;
while (l<=r)
{
if (get(mid,i)==a[i]) ret=mid,r=mid-1;
else l=mid+1;
}
dp[now][i]=(ll)a[i]*(i-ret+1);
Ans=max(Ans,dp[now][i]+(ll)(pos[i]-i-1)*a[i]);
B[i]=(ll)a[i]*(pos[i]-i-1);
}
for (int i=1;i<=k;i++)
{
last=now,now^=1;
memset(dp[now],0,sizeof(dp[now]));
solve(1,n);
for (int j=1;j<=n;j++)
Ans=max(Ans,dp[now][j]+B[j]);
}
printf("%lld\n",Ans);
}
return 0;
}
这题其实是比赛时看的第一道题。然后险些被吓死(好TM难)。然后梁大大看了一眼,求下一句“这就是个ZJOI2016旅行者的套路题”。然后我认真地%了一下梁大大的博客,然后终于会写了。。然后经过 n n hours,我终于过了样例,然后交了以后,欣喜地爆零啦。然后找梁大对拍。发现自己就是个斯波,横纵坐标每天写反不知道在干什么。然后就A了。
似乎无脑分层跑dijkstra跑出最短路树就没有了吧。。(可能还有个树上到根路径加和询问单点值,这个好像dfs+树状数组就好了吧)。
(为防止特殊情况 暂时删去代码)
第一次打challenge,完全不会(可能之前听梁大大说过一题)。
然后就无脑一个常数函数就没了。可能骗了42分。(可能还有一些奇奇怪怪的东西)
#include
#define gc getchar()
#define ll long long
#define N 109
#define lim 100
using namespace std;
int n,b[N][N],a[N][N],num,m,Num,num2;
struct node
{
int x,y;
node(int x=0,int y=0):x(x),y(y){}
}p[N*N];
struct line
{
int a1,a2,b1,b2,c1,c2,d,l,r;
bool operator <(const line &rhs) const
{
return (r-l+1)<(rhs.r-rhs.l+1);
}
line(int a1=0,int a2=0,int b1=0,int b2=0,int c1=0,int c2=0,int d=0,int l=0,int r=0):a1(a1),a2(a2),b1(b1),b2(b2),c1(c1),c2(c2),d(d),l(l),r(r){}
}ans[N*N],Ans[N*N],Ans_now[N*N],ans2[N*N];
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-'0';
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';
return x*s;
}
void dfs(int rest,int now,int Num_now)
{
if (Num_now>=min(num,Num)) return;
while (now<=m&&a[p[now].x][p[now].y]>1) now++;
if (m-now+1<=rest)
{
Num=Num_now;
for (int i=1;i<=Num;i++)
Ans[i]=Ans_now[i];
return;
}
int op=rand()%1000;
int d=max(rand()%(2*n+1)-n,p[now].y-n);
//p[now].x*x/y+d=p[now].y
int x=p[now].y-d,y=p[now].x;
int use,tmp;
if (rest==0) use=tmp=0;
else use=rand()%min(rest,3)+1,tmp=use;
int l=p[now].x;
while ((l<=n)&&((a[l][l*x/y+d])||(use>0))&&(l*x/y+d>=1&&l*x/y+d<=n))
{
if (a[l][l*x/y+d]) a[l][l*x/y+d]++;
else use--;
l++;
}
l--;
while (a[l][l*x/y+d]==0) l--,use++;
Ans_now[Num_now+1]=line(0,1,0,1,x,y,d,p[now].x,l);
dfs(rest-tmp+use,now+1,Num_now+1);
for (int i=p[now].x;i<=l;i++)
if (a[i][i*x/y+d]>1) a[i][i*x/y+d]--;
}
int main()
{
srand(19260817);
int T=read();
while (T--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
n=read(),m=0;
char ch;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
while (ch=gc,ch!='0'&&ch!='1');
b[i][j]=a[i][j]=ch-'0';
if (a[i][j]) p[++m]=node(i,j);
}
num=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]==1)
{
int x=i,y=j;
while (a[x][y]==1) x++,y++;
if (x-i>=30)
{
for (int k=i,l=j;k<x&&l<y;k++,l++)
a[k][l]=0;
ans[++num]=line(0,1,0,1,1,1,j-i,i,x-1);
continue;
}
if (i+j>n) continue;
x=i,y=j;
while (a[x][y]==1) x++,y--;
if (x-i>=30)
{
for (int k=i,l=j;k<x&&l>y;k++,l--)
a[k][l]=0;
ans[++num]=line(0,1,0,1,-1,1,i+j,i,x-1);
continue;
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]==1)
{
int now=i;
while (a[now][j]==1) now++;
now--;
for (int k=i;k<=now;k++) a[k][j]=0;
ans[++num]=line(0,1,0,1,0,1,j,i,now);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++) a[i][j]=b[i][j];
num2=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]==1)
{
int now=i;
while (a[now][j]==1) now++;
now--;
for (int k=i;k<=now;k++) a[k][j]=0;
ans2[++num2]=line(0,1,0,1,0,1,j,i,now);
}
int rest=lim;
sort(ans+1,ans+num+1);
int now=1;
while (now<=num&&rest>=ans[now].r-ans[now].l+1)
rest-=ans[now].r-ans[now].l+1,now++;
rest=lim;
sort(ans2+1,ans2+num2+1);
int now2=1;
while (now2<=num2&&rest>=ans2[now2].r-ans2[now2].l+1)
rest-=ans2[now2].r-ans2[now2].l+1,now2++;
if (num2-now2+11)
{
swap(num2,num);
swap(now2,now);
swap(ans2,ans);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++) a[i][j]=b[i][j];
Num=10000;
for (int i=0;i<100;i++)
{
random_shuffle(p+1,p+m+1);
dfs(lim,1,0);
}
if (Num>=num-now+1)
{
printf("%d\n",num-now+1);
for (int i=now;i<=num;i++)
printf("%d %d %d %d %d %d %d %d %d\n",ans[i].a1,ans[i].a2,ans[i].b1,ans[i].b2,ans[i].c1,ans[i].c2,ans[i].d,ans[i].l,ans[i].r);
}
else
{
printf("%d\n",Num);
for (int i=1;i<=Num;i++)
printf("%d %d %d %d %d %d %d %d %d\n",Ans[i].a1,Ans[i].a2,Ans[i].b1,Ans[i].b2,Ans[i].c1,Ans[i].c2,Ans[i].d,Ans[i].l,Ans[i].r);
}
}
return 0;
}
后记:
似乎rank14,果然比大佬们菜到不知道哪里去了。(话说楼教主突发出现,有点害怕啊)