2023.1.13 日寄
发现这东西被存成草稿了现在才发出来
一言
生活是苦难的,我又划着我的断桨出发了。—— 博尔赫斯
昨日(名义上的)复习内容:图论
Two Trees
题意
\(~~~~\) 两棵有根树 \(A,B\) 。给每个结点确定一个权值,使在两棵树上均满足任意结点子树权值和的绝对值为 \(1\)。给出构造方案或判断无解。
\(~~~~\) \(1\leq n\leq 10^5\).
题解
\(~~~~\) 先来看怎么判无解。发现如果一个点有奇数个儿子,那么它的值只能是偶数。如果一个点有偶数个儿子,那么它的值只能是奇数。如果不满足两棵树上的奇偶性一致那肯定无解。
\(~~~~\) 然后再来考虑怎么构造,不会,点开题解:“构造一个 \(2n+1\) 个结点的新图”,关闭题解。
\(~~~~\) 现在来考虑怎么做呢?首先 \(2n\) 个点可以想到去把两棵树全部放在原图上,此时所有应该为奇数的点都有奇数的度,应该为偶数的点都有偶数的度。(根除外)那为了排除根的特殊性,多的那个点就该连向两棵树的根。
\(~~~~\) 然后现在所有奇数点都有了奇数度,偶数点都有了偶数度。注意到新图上我们需要一些东西来做标记用来记录权值,那怎么搞呢?把所有奇数点对应的点之间连边,偶数点不连且默认构造值为 \(0\)。那么现在所有点都是偶度了,这不难想到欧拉回路,那我们来看看欧拉回路可以表示出什么构造呢?注意到两个奇数点之间有连边,那这条边在欧拉回路上的两种方向用来表示 \(\pm 1\) 呢?
\(~~~~\) 来考虑这种构造,没有连边的为 \(0\),其必定相邻了偶数个点:如果这个点不是根,那这些点中有一个是它的父亲,并且因为能构造欧拉回路,这个点相邻偶数个点一定一半上一半下,也就是逆向的,那不管哪一个是根,这个点的权值和就是 \(\pm 1\)。如果这个点是根,可以发现虚点起的作用和父亲类似,所以不管。
\(~~~~\) 那连了边的如果为 \(1\) ,我们不妨记录它为 \(A \rightarrow B\) 的方向,那加上这条边和相邻的边总共应该是一半 \(A \rightarrow B\) ,一半 \(B \rightarrow A\) ,还是去掉一个父亲或者虚点那和上面同理,所以构造是合理的。
代码
查看代码
#include <bits/stdc++.h>
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x*=f;
}
struct Edge{
int To,nxt;
}E[1000005];
bool vis[2000005];
int n,cnt=1,head[2000005],Ans[2000005];
int Son1[2000005],Son2[2000005],fa1[2000005],fa2[2000005];
void Add(int u,int v)
{
// if(u==460) cerr<<head[u]<<endl;
cnt++; E[cnt].To=v; E[cnt].nxt=head[u]; head[u]=cnt;
cnt++; E[cnt].To=u; E[cnt].nxt=head[v]; head[v]=cnt;
}
vector <int> Path;
void dfs(int u)
{
for(int i=head[u];i;)
{
// cerr<<head[460]<<" "<<E[head[460]].nxt<<" "<<u<<" "<<i<<" "<<endl;
// cerr<<u<<" "<<i<<endl;
if(vis[i>>1]) {head[u]=E[i].nxt;i=E[i].nxt;continue;}
vis[i>>1]=true; dfs(E[i].To);
if(1<=u&&u<=n&&n+1<=E[i].To&&E[i].To<=2*n) Ans[u]=1;
if(n+1<=u&&u<=2*n&&1<=E[i].To&&E[i].To<=n) Ans[E[i].To]=-1;
i=head[u];
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input","r",stdin);
freopen("output","w",stdout);
#endif
// memset(head,-1,sizeof(head));
read(n);
for(int i=1;i<=n;i++) read(fa1[i]),Son1[fa1[i]]++;
for(int i=1;i<=n;i++) read(fa2[i]),Son2[fa2[i]]++;
for(int i=1;i<=n;i++) if((Son1[i]&1)!=(Son2[i]&1)) return puts("IMPOSSIBLE")&0;
for(int i=1;i<=n;i++)
{
if(fa1[i]==-1) Add(2*n+1,i);
else Add(i,fa1[i]);
if(fa2[i]==-1) Add(2*n+1,i+n);
else Add(i+n,fa2[i]+n);
if(!(Son1[i]&1)) Add(i,i+n);
}
// cerr<<cnt<<endl;
dfs(1);
puts("POSSIBLE");
for(int i=1;i<=n;i++) printf("%d ",Ans[i]);
return 0;
}
/*
清夜无尘。月色如银。酒斟时、须满十分。浮名浮利,虚苦劳神。叹隙中驹,石中火,梦中身。
虽抱文章,开口谁亲。且陶陶、乐尽天真。几时归去,作个闲人。对一张琴,一壶酒,一溪云。
落日绣帘卷,亭下水连空。知君为我新作,窗户湿青红。长记平山堂上,欹枕江南烟雨,杳杳没孤鸿。认得醉翁语,山色有无中。
一千顷,都镜净,倒碧峰。忽然浪起,掀舞一叶白头翁。堪笑兰台公子,未解庄生天籁,刚道有雌雄。一点浩然气,千里快哉风。
我们可以分析出每个点取值的奇偶性,然后怎么做呢?
打开题解 -> 构造一个2n+1个点的图 -> 关闭题解
那么显然 2n 就是把所有点都列出来,两棵树先各自按自己的树边连边
注意到取值为奇数的点已经连了奇数条边,为偶数的点已经连了偶数条边(根除外)
首先为了排除根的特殊性给它连一个虚点。
然后奇数点对应连成偶数点,整个图都是偶度点,考虑欧拉回路。
那每个点的值就应该是由对应连边的去确定。
*/
「HNOI2019」 序列
题意
\(~~~~\) 对 \(A\) 构造非下降序列 \(B\) ,使得 \(\sum (A_i-B_i)^2\) 最小。同时 \(m\) 次询问,每次询问如果将 \(A_x\) 修改为 \(y\) 的答案。
\(~~~~\) \(3\leq n\leq 10^5,0\leq m\leq 10^5\).
题解
\(~~~~\) 注意到我们会把 \(B\) 构造成若干个值相等(均为 \(x\) )的子段,这些值为对应的 \(A\) 的子段的平均值,此时答案的值最小。并且每个分开的区间越短越好,那这样就会有唯一的构造 \(\{B\}\) 方案。
\(~~~~\) 维护的时候,我们就挨个把每个数先试图分开区间,如果发现这样平均值不满足不降的条件就合并到上一个区间。这样我们就可以单次 \(\mathcal{O(n)}\) 求答案。
\(~~~~\) 然后我们只需要考虑被修改那个点在之后的合理区间,前后的都按以前就行了。
代码
查看代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x*=f;
}
const ll MOD=998244353;
inline ll Add(ll x,ll y){return (x%MOD+y%MOD)%MOD;}
inline ll Dec(ll x,ll y){return (x%MOD-y%MOD+MOD)%MOD;}
inline ll Mul(ll x,ll y){return 1ll*x%MOD*(y%MOD)%MOD;}
ll qpow(ll a,ll b)
{
ll ret=1;
while(b)
{
if(b&1) ret=Mul(ret,a);
b>>=1;a=Mul(a,a);
}
return ret;
}
struct node{
ll len;ll Sum1,Sum2;
node(){}
node(ll Len,ll SUM1,ll SUM2){len=Len,Sum1=SUM1,Sum2=SUM2;}
}Sum[100005],Sta[100005];
node operator + (node a,node b){return node(Add(a.len,b.len),a.Sum1+b.Sum1,Add(a.Sum2,b.Sum2));}
node operator - (node a,node b){return node(Dec(a.len,b.len),a.Sum1-b.Sum1,Dec(a.Sum2,b.Sum2));}
bool operator < (node a,node b){return b.len?(a.len?1.0*a.Sum1/a.len<1.0*b.Sum1/b.len:1):0;}
bool operator <= (node a,node b){return b.len?(a.len?1.0*a.Sum1/a.len<=1.0*b.Sum1/b.len:1):0;}
node Query(ll l,ll r){return !l||!r?node(0,0,0):(Sum[r]-Sum[l-1]);}
ll n,m,Top,arr[100005],Inv[100005];
struct Node{
ll rt,Top;ll Ans;
}Pre[100005],Suf[100005];
struct SegmentTree{
#define ls ch[p][0]
#define rs ch[p][1]
ll tot;
ll ch[4000000][2],L[4000000],R[4000000],k[4000000];
inline void pushUp(ll p)
{
L[p]=L[ls];
if(rs) R[p]=R[rs]; else R[p]=R[ls];
k[p]=k[ls];
}
void Modify(ll &p,ll l,ll r,ll aim,ll lx,ll rx)
{
tot++; ch[tot][0]=ch[p][0],ch[tot][1]=ch[p][1],L[tot]=L[p],R[tot]=R[p],k[tot]=k[p]; p=tot;
if(l==r){L[p]=lx;R[p]=k[p]=rx;return;}
ll mid=(l+r)>>1;
if(aim<=mid) Modify(ls,l,mid,aim,lx,rx);
if(mid<aim) Modify(rs,mid+1,r,aim,lx,rx);
pushUp(p);
}
ll queryR(ll p,ll l,ll r,ll pos)
{
if(l==r) return R[p];
ll mid=(l+r)>>1;
if(pos<=mid) return queryR(ls,l,mid,pos);
return queryR(rs,mid+1,r,pos);
}
ll queryL(ll p,ll l,ll r,ll pos,node &val)
{
if(r<=pos)
{
node LVal=Query(L[p],k[p]),RVal=Query(k[p]+1,R[p]);
if(RVal+val<=LVal) {val=val+Query(L[p],R[p]);return 0;}
if(l==r) return R[p];
}
ll res=0,mid=(l+r)>>1;
if(pos>mid&&(res=queryL(rs,mid+1,r,pos,val))) return res;
else return queryL(ls,l,mid,pos,val);
}
#undef ls
#undef rs
}Seg;
void Prefix()
{
Top=0;
for(ll i=1;i<=n;i++)
{
Sta[++Top]=node(1,arr[i],Mul(arr[i],arr[i]));
while(Top>1&&Sta[Top]<=Sta[Top-1]) Sta[Top-1]=Sta[Top-1]+Sta[Top],Top--;
Pre[i].Ans=Add(Pre[i-Sta[Top].len].Ans,Dec(Sta[Top].Sum2,Mul(Mul(Sta[Top].Sum1,Sta[Top].Sum1),Inv[Sta[Top].len])));
Pre[i].Top=Top; Pre[i].rt=Pre[i-1].rt;
Seg.Modify(Pre[i].rt,1,n,Pre[i].Top,i-Sta[Top].len+1,i);
}
}
void Suffix()
{
Top=0;
for(ll i=n;i>=1;i--)
{
Sta[++Top]=node(1,arr[i],Mul(arr[i],arr[i]));
while(Top>1&&Sta[Top-1]<=Sta[Top]) Sta[Top-1]=Sta[Top-1]+Sta[Top],Top--;
Suf[i].Ans=Add(Suf[i+Sta[Top].len].Ans,Dec(Sta[Top].Sum2,Mul(Mul(Sta[Top].Sum1,Sta[Top].Sum1),Inv[Sta[Top].len])));
Suf[i].Top=Top; Suf[i].rt=Suf[i+1].rt;
Seg.Modify(Suf[i].rt,1,n,Suf[i].Top,i,i+Sta[Top].len-1);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input","r",stdin);
freopen("output","w",stdout);
#endif
read(n);read(m);
for(ll i=1;i<=n;i++) read(arr[i]),Sum[i]=Sum[i-1]+node(1,arr[i],Mul(arr[i],arr[i]));
Inv[1]=1; for(ll i=2;i<=n;i++) Inv[i]=Mul(Inv[MOD%i],(MOD-MOD/i));
Prefix(); Suffix(); printf("%lld\n",Pre[n].Ans);
ll x,y;
while(m--)
{
read(x);read(y);
ll l=0,r=Suf[x+1].Top-1;
while(l<=r)
{
ll mid=(l+r)>>1;
ll Rpos=mid?Seg.queryR(Suf[x+1].rt,1,n,Suf[x+1].Top-mid+1):x;
node Tmp=node(1,y,Mul(y,y))+Query(x+1,Rpos);
if(x>1) Seg.queryL(Pre[x-1].rt,1,n,Pre[x-1].Top,Tmp);
if(Tmp<Query(Rpos+1,Seg.queryR(Suf[x+1].rt,1,n,Suf[x+1].Top-mid))) r=mid-1;
else l=mid+1;
}
ll res=r+1;
ll Rpos=res?Seg.queryR(Suf[x+1].rt,1,n,Suf[x+1].Top-res+1):x;
node Tmp=node(1,y,Mul(y,y))+Query(x+1,Rpos);
ll Lpos=x>1?Seg.queryL(Pre[x-1].rt,1,n,Pre[x-1].Top,Tmp):x;
// cerr<<Dec(Tmp.Sum2,Mul(Mul(Tmp.Sum1,Tmp.Sum1),Inv[Tmp.len]))<<endl;
printf("%lld\n",Add(Dec(Tmp.Sum2,Mul(Mul(Tmp.Sum1,Tmp.Sum1),Inv[Tmp.len])),Add(Pre[Lpos].Ans,Suf[Rpos+1].Ans)));
}
return 0;
}
/*
清夜无尘。月色如银。酒斟时、须满十分。浮名浮利,虚苦劳神。叹隙中驹,石中火,梦中身。
虽抱文章,开口谁亲。且陶陶、乐尽天真。几时归去,作个闲人。对一张琴,一壶酒,一溪云。
落日绣帘卷,亭下水连空。知君为我新作,窗户湿青红。长记平山堂上,欹枕江南烟雨,杳杳没孤鸿。认得醉翁语,山色有无中。
一千顷,都镜净,倒碧峰。忽然浪起,掀舞一叶白头翁。堪笑兰台公子,未解庄生天籁,刚道有雌雄。一点浩然气,千里快哉风。
*/
「2019 集训队互测 Day 4」绝目编诗
题意
给出一个简单无向图,判断是否存在两个长度相同的简单环。
\(~~~~\) \(1\leq n\leq 10^4,1\leq m\leq 10^6\).
题解
\(~~~~\) 先考虑暴力怎么做?先从每个点开始暴力找环,我们注意到环的长度必定在 \([3,n]\) 之间,也就是说如果图上有 \(>n+2\) 个环,那由鸽巢原理必定存在等长的环。
\(~~~~\) 而我们得到原图的任意一棵生成树后,每条返祖边都会得到一个环,所以 \(n+3\) 条返祖边和 \(n-1\) 条树边必定是合法的。也就是说当 \(m \geq 2n+2\) 时答案就必定是 Yes
。
\(~~~~\) 现在我们已经把 \(m\) 缩小到和 \(n\) 相同的数量级了,继续怎么做呢?
\(~~~~\) 先打住,我们先来看下这个条件下怎么做?从每个点出发找环,但注意到每个环都会被走两次,每次都要走 \(i\) 的长度,所以复杂度是 \(\sum_{i=3}^n 2i^2=\mathcal{O(n^3)}\) 此外还需要 \(\mathcal{O(n)}\) 检查,所以是 \(\mathcal{O(n^4)}\) 的。
\(~~~~\) 然后看这个复杂度我们还需要优化到 \(\mathcal{O({\sqrt n}^2)}\) 级别,然后我们来见证魔法:
\(~~~~\) 我们随机删 \(\sqrt{n}\) 条边,那每个长度 \(i\) 的环就有 \((1-\frac{1}{\sqrt{n}})^i\) 的概率仍然留存,所以最后期望得到
\(~~~~\) 也就是说存在方案使得删 \(\sqrt{n}\) 条边过后剩下的环 \(\leq \sqrt{n}\) 个,然后再用 \(\sqrt{n}\) 条边可以删完,所以原图不超过 \(n+2\sqrt{n}\) 条边。
\(~~~~\) 然后我们把非树边变成关键点,建出来找环也就是在 \(\sqrt{n}\) 个点的图上找环,这样可以获得 \(\mathcal{O(n^2)}\) 的找法。
代码
查看代码
#include <bits/stdc++.h>
using namespace std;
const int M = 10005;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,k,tot=1,f[M],zz[M];vector<int> g[M];
int p[M],vis[M],dep[M],dis[M],len[M],cnt[M];
struct edge{int v,c,next;}e[M<<1];
void add(int u,int v,int c)
{
e[++tot]=edge{v,c,f[u]},f[u]=tot;
e[++tot]=edge{u,c,f[v]},f[v]=tot;
}
void dfs(int u,int fa)
{
int son=0;
dep[u]=dep[fa]+1;zz[u]=fa;
for(int v:g[u])
{
if(v==fa) continue;
if(dep[v])
{
if(dep[u]<dep[v]) continue;
if(!p[u]) p[u]=u;
if(!p[v]) p[v]=v;
add(p[u],p[v],1);
continue;
}
dfs(v,u);
if(p[v]) son=son?-1:p[v];
}
if(!p[u] && son<0) p[u]=u;
if(p[u])
{
for(int v:g[u]) if(zz[v]==u && p[v])
add(p[u],p[v],dep[p[v]]-dep[p[u]]);
}
else p[u]=son;
}
int check(int u,int nw)
{
if(!dep[u]) return 1;vis[u]=nw;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(vis[v]==nw || dep[v]>0) continue;
if(check(v,nw)) return 1;
}
return 0;
}
void work(int u,int fa)
{
if(!check(u,++k)) return ;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v,c=e[i].c,r=c+dis[u];
if(i==fa) continue;
if(!dep[v])//find root
{
if(!len[r]) len[r]=dep[u]+1;
if(len[r]!=dep[u]+1) {puts("Yes");exit(0);}
cnt[r]++;
if(cnt[r]>2*len[r]) {puts("Yes");exit(0);}
}
if(dep[v]>=0) continue;
dep[v]=dep[u]+1;dis[v]=r;
work(v,i^1);dep[v]=-1;
}
}
signed main()
{
n=read();m=read();
if(m>n+2*sqrt(n)) {puts("Yes");return 0;}
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++)
if(!dep[i]) dfs(i,0);
for(int i=1;i<=n;i++) dep[i]=-1;
for(int i=1;i<=n;i++) if(p[i]==i)
dep[i]=dis[i]=0,work(i,0),dep[i]=-1;
puts("No");
}
学习轨迹
题意
\(~~~~\) 在两个每个数带有价值的数列选出两个区间,使得 \([l_1,r_1]\) 和 \([l_2,r_2]\) 两个区间的元素不交且价值和最大.
\(~~~~\) \(1\leq n\leq 5\times 10^5\).
题解
\(~~~~\) 把两个数列放到二维平面上,那么元素相同的就是禁止选的点。我们要选一个矩形使得其周长最大。
\(~~~~\) 然后我们不难注意到元素价值的中间点必选,因为两个数列至少有答案:\(\max{(\sum{x_i},\sum{y_i})}\).
\(~~~~\) 那我们就考虑对某个轴选择了中间点,枚举另外一个轴选择的右端点,单调栈和线段树来维护左端点。
代码
查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x*=f;
}
bool Flag;
int n,m,l1,r1,l2,r2;
int a[1000005],b[1000005],Tmp[1000005];
ll Ans,Suma[1000005],Sumb[1000005];
inline void Update(ll ANS,int L1,int R1,int L2,int R2){if(Flag) swap(L1,L2),swap(R1,R2);if(ANS>Ans) Ans=ANS,l1=L1,r1=R1,l2=L2,r2=R2;}
struct SegmentTree{
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
ll Maxn[2000005],Val[2000005];
inline void pushUp(int p){Maxn[p]=max(Maxn[ls],Maxn[rs])+Val[p];}
void Build(int p,int l,int r)
{
Val[p]=0;
if(l==r) {Maxn[p]=Suma[n]-Sumb[l-1];return;}
int mid=(l+r)>>1;
Build(lson); Build(rson);
pushUp(p);
}
void Modify(int p,int l,int r,int lx,int rx,ll val)
{
if(lx<=l&&r<=rx) {Maxn[p]+=val;Val[p]+=val;return;}
int mid=(l+r)>>1;
if(lx<=mid) Modify(lson,lx,rx,val);
if(mid<rx) Modify(rson,lx,rx,val);
pushUp(p);
}
ll Query(int p,int l,int r)
{
if(l==r) return l;
int mid=(l+r)>>1;
if(Maxn[p]==Maxn[ls]+Val[p]) return Query(lson);
else return Query(rson);
}
#undef ls
#undef rs
#undef lson
#undef rson
}Seg;
int Sl[500005],Sr[500005],Topl,Topr;
void Solve()
{
int pos=lower_bound(Suma+1,Suma+1+n,(Suma[n]+1)/2)-Suma;
Topl=Topr=0; Seg.Build(1,1,m);
for(int i=1;i<=m;i++)
{
if(b[i])
{
if(b[i]<=pos)
{
while(Topl&&b[i]>b[Sl[Topl]]) Seg.Modify(1,1,m,Sl[Topl-1]+1,Sl[Topl],Suma[b[Sl[Topl]]]),Topl--;
Seg.Modify(1,1,m,Sl[Topl]+1,i,-Suma[b[i]]); Sl[++Topl]=i;
}
else
{
while(Topr&&b[i]<b[Sr[Topr]]) Seg.Modify(1,1,m,Sr[Topr-1]+1,Sr[Topr],Suma[n]-Suma[b[Sr[Topr]]-1]),Topr--;
Seg.Modify(1,1,m,Sr[Topr]+1,i,Suma[b[i]-1]-Suma[n]); Sr[++Topr]=i;
}
}
int j=Seg.Query(1,1,m);
int L=lower_bound(Sl+1,Sl+1+Topl,j)-Sl,R=lower_bound(Sr+1,Sr+1+Topr,j)-Sr;
L=(L<=Topl?b[Sl[L]]+1:1); R=(R<=Topr?b[Sr[R]]-1:n);
// cerr<<Flag<<" "<<L<<" "<<R<<" "<<j<<" "<<i<<endl;
Update(Sumb[i]+Seg.Maxn[1],L,R,j,i);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input","r",stdin);
freopen("output","w",stdout);
#endif
read(n);read(m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++) read(Suma[i]),Suma[i]+=Suma[i-1];
for(int i=1,x;i<=m;i++) read(x),Tmp[x]=i;
for(int i=1;i<=m;i++) read(Sumb[i]),Sumb[i]+=Sumb[i-1];
for(int i=1;i<=n;i++) a[i]=Tmp[a[i]],b[a[i]]=i;//把ai改成选i号位置的ban位
Update(Suma[n],1,n,0,0); Update(Sumb[m],0,0,1,m);
Solve(); swap(n,m); swap(a,b); swap(Suma,Sumb); Flag=true; Solve();
printf("%lld\n%d %d\n%d %d",Ans,l1,r1,l2,r2);
return 0;
}
/*
清夜无尘。月色如银。酒斟时、须满十分。浮名浮利,虚苦劳神。叹隙中驹,石中火,梦中身。
虽抱文章,开口谁亲。且陶陶、乐尽天真。几时归去,作个闲人。对一张琴,一壶酒,一溪云。
落日绣帘卷,亭下水连空。知君为我新作,窗户湿青红。长记平山堂上,欹枕江南烟雨,杳杳没孤鸿。认得醉翁语,山色有无中。
一千顷,都镜净,倒碧峰。忽然浪起,掀舞一叶白头翁。堪笑兰台公子,未解庄生天籁,刚道有雌雄。一点浩然气,千里快哉风。
5 7
5 4 9 2 3
395 964 318 763 523
7 12 3 2 5 6 11
479 31 145 778 384 566 349
*/
2023.01.13 日寄
\(~~~~\) 全是多项式,做不来。