Codeforces Round #545 Div1 题解
来写题解啦QwQ
本来想上红的,结果没做出D。。。。
A. Skyscrapers
题意
给定一个\(n*m\)的网格,每个格子里都有一个数,对于任意一行和任意一列,要求把这\(n+m-1\)个数重新用正整数编号,并且对于这一行,数与数之间的大小关系不变,对于这一列同理。求出任意一行和任意一列编号使用的最大编号的最小值。
题解
读题读半天。。。
看懂了题目就不难了。
对于每一行和每一列先分别离散,记录每个位置在离散后的值,
然后合并之后取较大的那个,然后剩下的部分顺次编号就行了。。
看看代码就懂了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 1010
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m;
int r[MAX],l[MAX];
int a[MAX][MAX],b[MAX][MAX],c[MAX][MAX];
int S[MAX],top;
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
a[i][j]=read();
for(int i=1;i<=n;++i)
{
top=0;
for(int j=1;j<=m;++j)S[++top]=a[i][j];
sort(&S[1],&S[top+1]);top=unique(&S[1],&S[top+1])-S-1;
for(int j=1;j<=m;++j)b[i][j]=lower_bound(&S[1],&S[top+1],a[i][j])-S;
r[i]=top;
}
for(int i=1;i<=m;++i)
{
top=0;
for(int j=1;j<=n;++j)S[++top]=a[j][i];
sort(&S[1],&S[top+1]);top=unique(&S[1],&S[top+1])-S-1;
for(int j=1;j<=n;++j)c[j][i]=lower_bound(&S[1],&S[top+1],a[j][i])-S;
l[i]=top;
}
for(int i=1;i<=n;++i,puts(""))
for(int j=1;j<=m;++j)
{
int ans1=max(r[i],max(l[j],b[i][j]+l[j]-c[i][j]));
int ans2=max(r[i],max(l[j],c[i][j]+r[i]-b[i][j]));
printf("%d ",max(ans1,ans2));
}
return 0;
}
B. Camp Schedule
翻译
给定一个串\(S\)以及一个串\(T\)。
现在要求把\(S\)打乱顺序,使得\(T\)在\(S\)中出现的次数最多。
题解
B比A显然简单多了啊,对于\(T\)跑\(KMP\)然后先建一次\(T\),然后每次跳到\(next\)接着往后放就行了。。。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 500500
char ch[MAX];
int n,m,nt[MAX];
int main()
{
scanf("%s",ch+1);
for(int i=1,l=strlen(ch+1);i<=l;++i)
if(ch[i]=='0')++n;else ++m;
scanf("%s",ch+1);int l=strlen(ch+1);
nt[1]=0;
for(int i=2;i<=l;++i)
{
int t=nt[i-1];
while(t&&ch[t+1]!=ch[i])t=nt[t];
if(!t)
{
if(ch[1]==ch[i])nt[i]=1;
else nt[i]=0;
}
else nt[i]=t+1;
}
bool fl=true;
for(int i=1;i<=l;++i)
if(ch[i]=='0'){if(!n){fl=false;break;}--n;putchar('0');}
else{if(!m){fl=false;break;}--m;putchar('1');}
while((n||m)&&fl)
{
for(int i=nt[l]+1;i<=l;++i)
if(ch[i]=='0'){if(!n){fl=false;break;}--n;putchar('0');}
else{if(!m){fl=false;break;}--m;putchar('1');}
}
while(n--)putchar('0');while(m--)putchar('1');puts("");
return 0;
}
C. Museums Tour
翻译
给定一张有向图,然后你在第\(0\)天从\(1\)号点出发,每个点都有一个博物馆,一周有\(d\)天,每个博物馆会以\(d\)为周期改变其开放状态,会告诉你一个串,表示这个点的博物馆在第\(t\%d\)天是否开放。
现在你想知道你在\(\infty\)天内最多可以访问多少个博物馆。
题解
首先显然缩点之后转\(DAG\),然后设\(f[i][t]\)表示在\(mod\ d\)意义下的第\(t\)天到达\(i\)这个\(scc\)能够访问到的最大博物馆数,如果能够预处理在这个\(scc\)内能够访问到的博物馆数以及出边,那么就可以按照拓扑序直接\(dp\)。
对于每一个\(scc\)内每一个环大小和\(d\)求一个\(gcd\),那么如果能够在\(t\)时刻访问到点\(i\),那么在\(t+k\ gcd\)时刻也能访问到\(i\),那么这样子就可以预处理出在\(t\)时刻到达这个\(scc\)上的某个特定点能够访问到的点数。
至于出边怎么处理,首先给同一个\(scc\)上的每个点按照随便一棵生成树的深度模\(gcd\)编个号,假装为\(val[u]\),假设有边\(u,v\)连接着两个不同的\(scc\),令\(G\)为两个\(scc\)的\(gcd\)的\(gcd\),那么这两个\(scc\)之间就可以连一个时间为\((val[u]-val[v]+1)\%G+k\times G\)的边。
这样子边数是\(m*d\),点数是\(n\),时间复杂度就是\(O(m*d+n)\)。
似乎我的方法的有点小复杂QwQ。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define MAX 200200
#define MOD 1000000007
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
int n,m,ty,d;
struct Line{int v,next;}e[MAX];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int dfn[MAX],low[MAX],tim;
int S[MAX],top;bool ins[MAX];
int scc,G[MAX];bool vis[MAX];
int val[MAX],GCD,g[MAX],D;
char V[MAX][51];
int pre[MAX][51];
void Work(int u,int p)
{
val[u]=p;vis[u]=true;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(G[v]!=scc)continue;
if(!vis[v])Work(v,p+1);
else GCD=__gcd(GCD,abs(p+1-val[v]));
}
}
int A[MAX];
void Tarjan(int u)
{
dfn[u]=low[u]=++tim;ins[u]=true;S[++top]=u;
for(int i=h[u];i;i=e[i].next)
if(!dfn[e[i].v])Tarjan(e[i].v),low[u]=min(low[u],low[e[i].v]);
else if(ins[e[i].v])low[u]=min(low[u],dfn[e[i].v]);
if(dfn[u]==low[u])
{
int v,tot=0;++scc;
do{v=S[top--];ins[v]=false;G[v]=scc;A[++tot]=v;}while(u!=v);
GCD=D;Work(u,0);g[scc]=GCD;
for(int i=0;i<GCD;++i)
for(int j=1;j<=tot;++j)
for(int k=i;k<D;k+=GCD)
if(V[A[j]][k]=='1'){V[A[j]][i]='1';break;}
for(int i=0;i<GCD;++i)
{
for(int j=1;j<=tot;++j)
if(V[A[j]][(val[A[j]]+i)%GCD]=='1')
++pre[scc][i];
}
}
}
struct Edge{int v,next,d;}E[MAX*50];
int H[MAX],Cnt=1,dg[MAX];
inline void Add(int u,int v,int d){E[Cnt]=(Edge){v,H[u],d};H[u]=Cnt++;dg[v]++;}
int ans,f[MAX][55];
void DP()
{
memset(f,-63,sizeof(f));f[G[1]][0]=pre[G[1]][0];
queue<int> Q;
for(int i=1;i<=scc;++i)if(!dg[i])Q.push(i);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=H[u];i;i=E[i].next)
if(!--dg[E[i].v])Q.push(E[i].v);
for(int t=0;t<D;++t)
for(int i=H[u];i;i=E[i].next)
{
int v=E[i].v,d=E[i].d;
f[v][(t+d)%D]=max(f[v][(t+d)%D],f[u][t]+pre[v][(t+d)%g[v]]);
}
for(int t=0;t<D;++t)ans=max(ans,f[u][t]);
}
printf("%d\n",ans);
}
int main()
{
n=read();m=read();D=read();
for(int i=1,x,y;i<=m;++i)x=read(),y=read(),Add(x,y);
for(int i=1;i<=n;++i)scanf("%s",V[i]);
for(int i=1;i<=n;++i)if(!dfn[i])Tarjan(i);
for(int u=1;u<=n;++u)
for(int i=h[u];i;i=e[i].next)
{
if(G[u]==G[e[i].v])continue;
int U=G[u],V=G[e[i].v];
int dd=__gcd(g[U],g[V]);
int d=(val[u]-val[e[i].v]+1+D)%D;
for(int j=d%dd;j<D;j+=dd)Add(U,V,j);
}
DP();
return 0;
}
D. Cooperative Game
翻译
交互题
有一张图是由一个长度为\(t\)的链和一个大小为\(c\)的环中间连上一条边组成的。
假如这条边连接的是链的右端点,和环上的\(T\)点。
令链的左端点是\(S\)。
现在在\(S\)处有\(10\)个棋子,编号\(0-9\),每次你可以让任意数量的棋子向出边方向走一步,交互库会返回若干个集合,每一个集合内的棋子都在同一个位置上,并且这个位置上的所有棋子都在这个集合中。
现在你既不知道\(t\)也不知道\(c\)。你需要使用不超过\(3(t+c)\)次操作使得所有棋子都移动到\(T\)位置上并且返回交互库done
。
题解
其实我差不多快做出来了。。。。
首先让两个棋子移动,一个每次操作都向前走,另外一个每两次操作才向前走。
当两个棋子相遇时停止。
把环按照\(T\)点开始沿出边方向标号。
假设当第二个棋子位于\(T\),即\(0\)位置时,假设第一个棋子在\(p\)位置。
因为第一个棋子每次比第二个棋子多走一步,距离差是\(c-p\)。
所以接下来第二个棋子要移动的步数就是\(c-p\)。所以相遇时两个棋子在\(c-p\)位置。
因为第二个棋子到达\(T\)时走了\(t\)步,此时第一个棋子走了\(2t\)步,即他在环上走了\(t\)步,所以有\(t\mod c=p\),那么让\(10\)个棋子同时向前走,当所有棋子位于同一个点时他们就同时到达了\(T\) 。
即这里还需要走\(t\)步,而这\(t\)步等价于在环上走了\(p\)步,那么\(1,2\)两个棋子就从\(c-p\)走到了\(0\)位置即\(T\)。
#include<iostream>
#include<cstdio>
using namespace std;
char ch[20];
int Read(){fflush(stdout);int x;scanf("%d",&x);for(int i=1;i<=x;++i)scanf("%s",ch);return x;}
int main()
{
while(233)
{
printf("next 0\n");Read();
printf("next 0 1\n");
int tot=Read();
if(tot==2)break;
}
while(233)
{
printf("next 0 1 2 3 4 5 6 7 8 9\n");fflush(stdout);
if(Read()==1)break;
}
printf("done");fflush(stdout);
}
E. Train Car Selection
翻译
你有一列有\(n\)个车厢的火车,从车头开始\(1-n\)编号。
现在有\(3\)种操作,第一种是在车头位置加入\(k\)节车厢,第二种位置是在车尾位置加入\(k\)节车厢,第三种是修改每节车厢的价值。
价值是这样子来的:一开始所有车厢的价值都是\(0\)(包括中途加入的车厢),然后每次修改会给定\(s,b\),如果当前车厢是从车头开始数的第\(i\)节,那么它的价值就会加上\((i-1)*s+b\)。
在每次操作结束之后回答价值最小的车厢的编号以及其价值。如果有多个输出编号最小的那个。
题解
发现每次一起加入进来的东西只需要维护左端点就好了。
首先如果在前端插入一段,那么后面全部都没用了,可以直接丢到。
否则在后面插入一段,维护一下当前全局加的一次函数是什么,那么每个左端点按照车厢编号+权值可以写成一个个的点,显然只有一个上凸壳才有用,那么维护这个上凸壳就行了。
#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 300300
#define ll long long
#define pi pair<ll,ll>
#define fr first
#define sd second
#define mp make_pair
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
pi p[MAX];
int n,m,r=1;ll k=0,b=0;
double Slope(pi a,pi b){return 1.0*(a.sd-b.sd)/(a.fr-b.fr);}
ll calc(pi x){return k*x.fr+x.sd+b;}
int main()
{
n=read();m=read();p[1]=mp(0,0);r=1;
while(m--)
{
int opt=read();
if(opt==1)r=1,p[1]=mp(0,0),k=b=0,n+=read();
else if(opt==2)
{
pi now=mp(n,-(n*k+b));
while(r>1&&Slope(now,p[r])<=Slope(p[r],p[r-1]))--r;
p[++r]=now;n+=read();
}
else b+=read(),k+=read();
while(r>1&&calc(p[r])>=calc(p[r-1]))--r;
printf("%I64d %I64d\n",p[r].fr+1,calc(p[r]));
}
return 0;
}
F. Matches Are Not a Child's Play
这题目名称真带感
翻译
有一个善良的人不想烧树,所以她决定在脑子里模拟烧树的过程。
我们认为树在燃烧的过程是这样的:每一个点有一个独一无二的优先级,每次烧掉优先级最小的那个叶子节点。
现在有若干次操作:
要么把一个点的优先级变为全局优先级的最大值+1,要么询问一个点什么时候被烧掉,要么询问两个点谁先被烧掉。
初始时\(i\)号点的优先级是\(i\)。
题解
显然两个询问是一样的东西。
加入我们已经知道了点与点之间的燃烧顺序,那么考虑一次修改操作对于燃烧次序的影响。
假设修改的点是\(x\),修改前优先级最大的点是\(y\)。
显然除了\(x-y\)这条链之外,其他点的燃烧相对循序是不变的。
在烧完其他的点之后会从\(y\)一直烧到\(x\)。
我们考虑一次修改操作,认为它就是把\(x-y\)链上的所有点重新染上一种颜色。
那么回答\(x\)被燃烧的时间,就是颜色编号比它小的点的个数再来加上颜色相同且要在他之前燃烧的点的数量。
那么我们用一个\(LCT\)来维护这个操作,强制每次\(LCT\)的根节点都是当前全局颜色最大的节点。
这样子修改点的优先级的时候,只需要直接\(makeroot\)就行了。
那树状数组维护颜色的前缀和,那么询问一个点的时候就是所有颜色不小于它的点数,再减去其在\(LCT\)上同色的祖先,即\(Splay\)之后的左子树大小。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 200200
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct BIT
{
int c[MAX<<1],n;
int lb(int x){return x&(-x);}
void Modify(int x,int w){while(x<=n)c[x]+=w,x+=lb(x);}
int Query(int x){int s=0;while(x)s+=c[x],x-=lb(x);return s;}
}C;
struct Node{int ch[2],ff,rev,sz,col,tag;}t[MAX];
bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
void pushup(int x){t[x].sz=t[ls].sz+t[rs].sz+1;}
void rotate(int x)
{
int y=t[x].ff,z=t[y].ff;
int k=t[y].ch[1]==x;
if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;t[y].ff=x;
pushup(y);pushup(x);
}
void putrev(int x){swap(ls,rs);t[x].rev^=1;}
void puttag(int x,int w){t[x].col=t[x].tag=w;}
void pushdown(int x)
{
if(t[x].rev)putrev(ls),putrev(rs),t[x].rev^=1;
if(t[x].tag)puttag(ls,t[x].tag),puttag(rs,t[x].tag),t[x].tag=0;
}
int S[MAX],top;
void Splay(int x)
{
S[top=1]=x;
for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
while(top)pushdown(S[top--]);
while(!isroot(x))
{
int y=t[x].ff,z=t[y].ff;
if(!isroot(y))
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
}
void access(int x,int col)
{
for(int y=0;x;y=x,x=t[x].ff)
{
Splay(x),rs=0,pushup(x);
C.Modify(t[x].col,-t[x].sz);
puttag(x,col);
C.Modify(t[x].col,t[x].sz);
rs=y;pushup(x);
}
}
int When(int x){Splay(x);return C.Query(t[x].col)-t[ls].sz;}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int n,Q;char ch[10];
void Build(int x,int ff)
{
t[x].col=x;t[x].sz=1;t[x].ff=ff;
for(int i=h[x];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
Build(v,x);t[x].col=max(t[x].col,t[v].col);
}
for(int i=h[x];i;i=e[i].next)
if(e[i].v!=ff&&t[x].col==t[e[i].v].col)
rs=e[i].v,t[x].sz+=t[e[i].v].sz;
C.Modify(t[x].col,1);
}
int main()
{
n=read();Q=read();C.n=n+Q+1;
for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
Build(n,0);int color=n;
while(Q--)
{
scanf("%s",ch);
if(ch[0]=='u')
{
int x=read();
access(x,color);
Splay(x);putrev(x);pushdown(x);
C.Modify(t[x].col,-1);
rs=0;puttag(x,++color);
t[x].sz=1;
C.Modify(t[x].col,1);
}
else if(ch[0]=='w')printf("%d\n",When(read()));
else
{
int x=read(),y=read();
if(When(x)<When(y))printf("%d\n",x);
else printf("%d\n",y);
}
}
return 0;
}
Codeforces Round #545 Div1 题解的更多相关文章
-
Codeforces Round #543 Div1题解(并不全)
Codeforces Round #543 Div1题解 Codeforces A. Diana and Liana 给定一个长度为\(m\)的序列,你可以从中删去不超过\(m-n*k\)个元素,剩下 ...
-
Codeforces Round #539 Div1 题解
Codeforces Round #539 Div1 题解 听说这场很适合上分QwQ 然而太晚了QaQ A. Sasha and a Bit of Relax 翻译 有一个长度为\(n\)的数组,问有 ...
-
Codeforces Round #545 (Div. 1) 简要题解
这里没有翻译 Codeforces Round #545 (Div. 1) T1 对于每行每列分别离散化,求出大于这个位置的数字的个数即可. # include <bits/stdc++.h&g ...
-
Educational Codeforces Round 64 部分题解
Educational Codeforces Round 64 部分题解 不更了不更了 CF1156D 0-1-Tree 有一棵树,边权都是0或1.定义点对\(x,y(x\neq y)\)合法当且仅当 ...
-
Educational Codeforces Round 64部分题解
Educational Codeforces Round 64部分题解 A 题目大意:给定三角形(高等于低的等腰),正方形,圆,在满足其高,边长,半径最大(保证在上一个图形的内部)的前提下. 判断交点 ...
-
Codeforces Round div2 #541 题解
codeforces Round #541 abstract: I构造题可能代码简单证明很难 II拓扑排序 III并查集 启发式排序,带链表 IV dp 处理字符串递推问题 V 数据结构巧用:于二叉树 ...
-
[Codeforces Round #254 div1] C.DZY Loves Colors 【线段树】
题目链接:CF Round #254 div1 C 题目分析 这道题目是要实现区间赋值的操作,同时还要根据区间中原先的值修改区间上的属性权值. 如果直接使用普通的线段树区间赋值的方法,当一个节点表示的 ...
-
[Codeforces Round #461 (Div2)] 题解
[比赛链接] http://codeforces.com/contest/922 [题解] Problem A. Cloning Toys [算法] 当y = 0 , 不可以 当 ...
-
Educational Codeforces Round 63部分题解
Educational Codeforces Round 63 A 题目大意就不写了. 挺简单的,若果字符本来就单调不降,那么就不需要修改 否则找到第一次下降的位置和前面的换就好了. #include ...
随机推荐
-
codeforces Simple Molecules
link:http://codeforces.com/contest/344/problem/B 刚开始想复杂了.一开始就想当然地以为可以有多个点,其实,人家题目要求只有3个点啊! 然后题目就简单了. ...
-
servletconfig和servletContext的区别
1.servletConfig: 在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数.(配置在某个servlet标签或者整个we ...
-
【坑】log4j-over-slf4j.jar AND slf4j-log4j12.jar的冲突问题
为了解决这个问题,已经有砸电脑的冲动了.通过百度查找都说是Maven依赖的原因,经过各种尝试仍然没有解决,后来终于在QQ群的帮助下,算是暂时过关. [问题] 程序在本地运行没有问题,打成jar包发布到 ...
-
Oracle报错:ORA-01747: user.table.column, table.column 或列说明无效
1.检查sql书写正确性 2.如果sql书写正确,则是由于数据库列名起的不好引起的,名字用到了数据库的关键字. 如果列很多,又不好确定是哪个列名使用了关键字,以下建议可供参考: 我用以下方法定位 se ...
-
c语言局部变量 静态局部变量 全局变量与静态全局变量
基本概念: 作用域:起作用的区域,也就是可以工作的范围. 代码块:所谓代码块,就是用{}括起来的一段代码. 数据段:数据段存的是数,像全局变量就是存在数据段的 代码段:存的是程序代码,一般是只读的. ...
-
matlab批量读取一个文件夹里类似命名的mat文件
参考网址: Matlab读取同一路径下多个txt或mat文件总结 matlab 批量读取数据文件.mat .dat 整理:matlab批量读入数据文件的方法 首先命名方式体现在只是名字里数字有变化,其 ...
-
Redis系列二:reids介绍
一.什么是redis.redis有哪些特性.redis有哪些应用场景.redis的版本 1. 什么是redis redis是一种基于键值对(key-value)数据库,其中value可以为string ...
-
java判断集合是否重复的一种便捷方法
内容来自其它网站,感谢原作者! import java.util.ArrayList; import java.util.HashSet; import java.util.List; /** * 通 ...
-
Python中的类属性、实例属性与类方法、静态方法
1.什么是类对象,实例对象 类对象:类名 实例对象:类创建的对象 2.类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++.Java中类的静态成员变量有点 ...
-
ctime 时间
1. 类型clock_t: 是个long型,用来记录一段时间内的时钟计时单元数,即CPU的运行单元时间.size_t: 标准C库中定义的,应为unsigned int,在64位系统中为long uns ...