@

2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛

CSDN

6702 &

\(1 and 1\)的话,\(c\)就必须为\(1\)。其他的贪心选\(0\).

注意c为正整数,0的话就取最低位1.

#include <iostream>
#define ll long long
using namespace std;
void solve(ll a,ll b) {
ll c=0;
for(ll i=31;i>=0;--i) {
bool k1=a&(1LL<<i),k2=b&(1LL<<i);
if(k1==1&&k2==1) c|=1LL<<i;
} if(c) return cout<<c<<"\n",void();
for(ll i=31;i>=0;--i) {
bool k1=a&(1LL<<i),k2=b&(1LL<<i);
if(k1||k2) c=1LL<<i;
} cout<<c<<"\n";
}
int main() {
int T;
cin>>T;
while(T --> 0) {
ll a,b;
cin>>a>>b;
solve(a,b);
}
return 0;
}

6703 array

修改操作其实是删除操作。

考虑不删除的话,就是把删除的数字放入\(set\)中

最终答案就是不删除的\(ans\)和\(set\)中符合条件的取个最小值。

方法一

建立主席树维护区间和。

二分,主席树\(check\)。

复杂度\(O(nlog^2n)\),实测\(T\)飞。

方法二

主席树上二分。

主席树不变查询区间和。然后找到第一个包含的满足条件的子区间。

条件就是\(r-l+1 < e[rt].tot\),然后再在这个区间上查一次就行了。

复杂度都是\(O(nlogn)\)

问了个当场切的老哥的代码,直接线段树,也没\(set\)直接改,我这里先\(Orz\)了。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <set>
#define ls(x) e[x].l
#define rs(x) e[x].r
#define _ 100007
using namespace std;
inline char nc() {
static char buf[3000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread (buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,a[_],cnt,rt[_];
set<int> dsr;
struct node{int l,r,siz;}e[_*20];
void insert(int l,int r,int pos,int val,int x,int &y) {
e[y=++cnt]=e[x];
e[y].siz++;
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) insert(l,mid,pos,val,ls(x),ls(y));
else insert(mid+1,r,pos,val,rs(x),rs(y)); }
int lastans,flag;
int ask(int l,int r,int x) {
if(l==r) return l;
int mid=(l+r)>>1;
if(e[ls(x)].siz<mid-l+1) return ask(l,mid,ls(x));
else return ask(mid+1,r,rs(x));
}
void query(int l,int r,int L,int R,int x) {
if(L<=l) {
if(!flag&&e[x].siz!=r-l+1) {
flag=1,lastans=min(lastans,ask(l,r,x));
} return;
}
int mid=(l+r)>>1;
if(L<=mid&&!flag) query(l,mid,L,R,ls(x));
if(R>mid&&!flag) query(mid+1,r,L,R,rs(x));
}
int main() {
int T=read();
while(T --> 0) {
dsr.clear(),dsr.insert(0x3f3f3f3f);
cnt=0;
for(int i=1;i<=n;++i) rt[i]=0;
for(int i=1;i<=cnt;++i) e[i]={};
n=read(),m=read();
for(int i=1;i<=n;++i) a[i]=read(),insert(1,n+1,a[i],a[i],rt[i-1],rt[i]);
rt[n+1]=rt[n];
lastans=0;
for(int i=1;i<=m;++i) {
int opt=read();
if(opt==1) {
int pos=read()^lastans;
if(!dsr.count(a[pos])) dsr.insert(a[pos]);
} else {
int r=read()^lastans,k=read()^lastans;
lastans=*dsr.lower_bound(k),flag=0;
query(1,n+1,k,n+1,rt[r]);
printf("%d\n",lastans);
}
}
}
return 0;
}

6704 K-th occurrence

想了想,只会后缀数组+二分+主席树,感觉有点恐怖就没写,最后还是写了。

然后套了个后缀数组板子就过了,实现还是挺简单的一点也不恐怖。

先对串串进行一遍后缀排序。

显然符合条件的串是一个区间,用Lcp进行二分来找到边界。

边界长度不够k就是-1,否则就查询区间的第k小,用主席树维护即可。

#include <bits/stdc++.h>
using namespace std;
const int _=2e5+7;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,Q,rt[_];
char s[_];
namespace SA {
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define ROF(i,a,b) for(int i=a;i>=b;--i)
int sa[_],rk[_],c[_],x[_],height[_],st[_][21];
void clear() {
memset(sa,0,sizeof(sa));
memset(rk,0,sizeof(rk));
memset(c,0,sizeof(c));
memset(x,0,sizeof(x));
memset(height,0,sizeof(height));
memset(st,0,sizeof(st));
}
void get_sa() {
int m=300;
FOR(i,1,n) ++c[rk[i]=s[i]];
FOR(i,1,m) c[i]+=c[i-1];
ROF(i,n,1) sa[c[rk[i]]--]=i;
for(int k=1;k<=n;k<<=1) {
int p=0;
FOR(i,n-k+1,n) x[++p]=i;
FOR(i,1,n) if(sa[i]>k) x[++p]=sa[i]-k;
FOR(i,1,m) c[i]=0;
FOR(i,1,n) ++c[rk[i]];
FOR(i,1,m) c[i]+=c[i-1];
ROF(i,n,1) sa[c[rk[x[i]]]--]=x[i],x[i]=0;
swap(rk,x);
rk[sa[1]]=1,p=1;
FOR(i,2,n) rk[sa[i]]=(x[sa[i]]==x[sa[i-1]]&&x[sa[i]+k]==x[sa[i-1]+k]) ? p : ++p;
if(p==n) break;
m=p;
}
}
void get_height() {
FOR(i,1,n) rk[sa[i]]=i;
int k=0;
FOR(i,1,n) {
k=k?k-1:0;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k]&&i+k<=n&&j+k<=n) k++;
height[rk[i]]=k;
}
height[0]=0;
FOR(i,1,n) st[i][0]=height[i];
FOR(j,1,20)
for(int i=1;i+(1<<j)-1<=n;++i)
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int LCP(int i,int j) {
if(i-1==j) return n-sa[i-1]+1;
int x=log2(j-i+1);
return min(st[i][x],st[j-(1<<x)+1][x]);
}
}
namespace TREE {
#define ls(x) e[x].l
#define rs(x) e[x].r
struct node {int l,r,siz;}e[_*32];
int cnt;
void insert(int l,int r,int L,int x,int &y) {
e[y=++cnt]=e[x];
e[y].siz++;
if(l==r) return;
int mid=(l+r)>>1;
if(L<=mid) insert(l,mid,L,ls(x),ls(y));
else insert(mid+1,r,L,rs(x),rs(y));
}
int query(int l,int r,int k,int x,int &y) {
if(l==r) return l;
int mid=(l+r)>>1,w=e[ls(y)].siz-e[ls(x)].siz;
if(k<=w) return query(l,mid,k,ls(x),ls(y));
else return query(mid+1,r,k-w,rs(x),rs(y));
}
}
void solve(int S,int T,int k) {
int L,R,l,r;
l=1,r=SA::rk[S];
while(l<=r) {
int mid=(l+r)>>1;
if(SA::LCP(mid+1,SA::rk[S])>=T-S+1) L=mid,r=mid-1;
else l=mid+1;
}
l=SA::rk[S],r=n;
while(l<=r) {
int mid=(l+r)>>1;
if(SA::LCP(SA::rk[S]+1,mid)>=T-S+1) R=mid,l=mid+1;
else r=mid-1;
}
// cout<<SA::rk[S]<<"\n";
// cout<<L<<" "<<R<<"\n";
if(R-L+1<k) return puts("-1"),void();
printf("%d\n",TREE::query(1,n,k,rt[L-1],rt[R]));
}
int main() {
int T=read();
while(T --> 0) {
//clear
memset(rt,0,sizeof(rt));
memset(TREE::e,0,sizeof(TREE::e));
TREE::cnt=0;
SA::clear();
//init
n=read(),Q=read();
scanf("%s",s+1);
n=strlen(s+1);
SA::get_sa();
SA::get_height();
for(int i=1;i<=n;++i) TREE::insert(1,n,SA::sa[i],rt[i-1],rt[i]);
//debug
// puts("sa : ");
// for(int i=1;i<=n;++i) cout<<SA::sa[i]<<" ";
// puts("\nrk : ");
// for(int i=1;i<=n;++i) cout<<SA::rk[i]<<" ";
// cout<<"\n";
// puts("LCP");
// for(int i=1;i<=n;++i) {
// for(int j=1;j<=n;++j) {
// if(i>j) printf("0 ");
// else printf("%d ",SA::LCP(i+1,j));
// }
// printf("\n");
// }
//query
while(Q --> 0) {
int l=read(),r=read(),k=read();
solve(l,r,k);
}
}
return 0;
}

6705 path

类似于NOI2010超级钢琴十二省联考的异或粽子

往这里思考过,不知道咋的\(3s\)后就放弃了,也许是当时觉得不对?

现在一看很对啊。

首先我们每个点连出的边按照权值排序。

用一个优先队列维护每个点为起始点的没被选中的最短路径,每次堆上找到最小的,然后删掉。

之后我们要加入两条要成为最短的可能路径。

1.\(t\)之后找一条最小的边接上。

2.若与\(t\)相连的上一个点为\(s,<s,t>\)这条边为第k大,则起点\(->s+k+1\)大边。

路径权值\(w\)对应着加加减减。

这里初始点不用记录,只记录\(s,t,k,w\)就行了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int _=5e4+7;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int ask[_];ll ans[_];
struct node{
int s,t,k;ll w;
node(int a,int b,int c,ll x) {s=a,t=b,k=c,w=x;}
};
bool operator < (node a,node b) {
return a.w>b.w;
}
priority_queue<node> q;
vector< pair<ll, int> > G[_];
int main() {
int T=read();
while(T --> 0) {
int n=read(),m=read(),Q=read(),cnt=0,limit=0;
while(!q.empty()) q.pop();
for(int i=1;i<=n;++i) G[i].clear();
for(int i=1;i<=m;++i) {
int u=read(),v=read(),w=read();
G[u].push_back(make_pair(w,v));
}
for(int i=1;i<=n;++i) {
sort(G[i].begin(),G[i].end());
if(G[i].size()) q.push(node(i,G[i][0].second,0,G[i][0].first));
}
for(int i=1;i<=Q;++i) ask[i]=read(),limit=max(limit,ask[i]);
while(!q.empty()&&cnt<limit) {
node u=q.top();q.pop();
ans[++cnt]=u.w;
if(u.k+1<(int)G[u.s].size())
q.push(node(u.s,G[u.s][u.k+1].second,u.k+1,u.w-G[u.s][u.k].first+G[u.s][u.k+1].first));
if(G[u.t].size()>0)
q.push(node(u.t,G[u.t][0].second,0,u.w+G[u.t][0].first));
}
for(int i=1;i<=Q;++i) printf("%lld\n",ans[ask[i]]);
}
return 0;
}

6706 huntian oy

\(gcd(i^a-j^a,i^b-j^b)=i-j(a,b互质)\)

求\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}(i-j)[(i,j)=1]\)

\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}i-\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}j([(i,j)=1])\)

与他互质的和为\(\frac{n*\phi(n)}{2},因为i\)对应\(n-i\)

\(\sum\limits_{i=1}^{n}i*\phi(i)-\sum\limits_{i=1}^{n}(\frac{i*\phi(i)}{2}+[i==1])\)

\(\frac{(\sum\limits_{i=1}^{n}i*\phi(i))-1}{2}\)

用杜教筛来求\(i*\phi(i)\)的前缀和就行了。

\(f(x)=x*\phi(x)\)

\((f*g)(n)=\sum\limits_{d|n}g(d)*\phi(\frac{n}{d})*\frac{n}{d}\)

显然\(g(i)为id(i)\)最合适。

\((f*g)(n)=n*\sum\limits_{d|n}\phi(\frac{n}{d})=n^2\)

\(g(1)S(n)=\sum\limits_{i=1}^{n}g(i)S(\frac{n}{i})-\sum\limits_{i=2}^{n}g(i)S(\frac{n}{i})\)

\(S(n)=\sum\limits_{i=1}^{n}i^2-\sum\limits_{i=2}^{n}iS(\frac{n}{i})\)

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int _=5e6+7,mod=1e9+7,limit=5000000;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int inv_2,inv_6,vis[_],pri[_],cnt;
ll phi[_];
int q_pow(int a,int b) {
int ans=1;
while(b) {
if(b&1) ans=1LL*ans*a%mod;
a=1LL*a*a%mod,b>>=1;
} return ans;
}
void Euler() {
vis[1]=phi[1]=1;
for(int i=1;i<=limit;++i) {
if(!vis[i]) pri[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&pri[j]*i<=limit;++j) {
vis[pri[j]*i]=1;
if(i%pri[j]==0) {
phi[i*pri[j]]=phi[i]*pri[j];
break;
} else phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
for(int i=2;i<=limit;++i) phi[i]=(phi[i-1]+1LL*phi[i]*i%mod)%mod;
}
unordered_map<int,int> ans_phi;
int get(int n) {return 1LL*n*(n+1)/2%mod;}
int solve_phi(int n) {
if(n<=limit) return phi[n];
if(ans_phi[n]) return ans_phi[n];
ll tmp=1LL*n*(n+1)%mod*(2*n+1)%mod*inv_6%mod;
for(int l=2,r;l<=n;l=r+1) {
r=n/(n/l),
tmp-=1LL*(get(r)-get(l-1))*solve_phi(n/l)%mod,
tmp=(tmp%mod+mod)%mod;
} return ans_phi[n]=tmp;
}
int main() {
inv_2=q_pow(2,mod-2),inv_6=q_pow(6,mod-2);
Euler();
int T=read();
while(T --> 0) {
int N=read();
int ans=1LL*(solve_phi(N)-1)*inv_2%mod;
ans=(ans%mod+mod)%mod;
printf("%d\n",ans);
N=read(),N=read();
}
return 0;
}

6707 Shuffle Card

想了半天也不会啊,平衡树还很麻烦,不想写。

其实倒着做就行了,用\(stack\)其实本质也是倒着做。

#include <bits/stdc++.h>
using namespace std;
const int _=2e5+7;
int n,m,a[_],b[_],vis[_];
vector<int> ans;
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=m;++i) scanf("%d",&b[i]);
for(int i=m;i>=1;--i) {
if(vis[b[i]]) continue;
vis[b[i]]=1;
ans.push_back(b[i]);
}
for(int i=1;i<=n;++i) {
if(vis[a[i]]) continue;
ans.push_back(a[i]);
}
for(int i=0;i<n;++i) cout<<ans[i]<<" ";
return 0;
}

6708 Windows Of CCPC

这是\(yjg\)外出模拟赛的\(luogu\)原题啊,\(axm\)还拉我做过,把\(0,1\)改成了\(C,P\)了而已。

递归即可。

分成四块,先递归第一块,剩下的三块复制第一块的内容,然后第四块取反。

#include <bits/stdc++.h>
using namespace std;
const int _=1207;
int n,A[_][_];
void copp(int x,int y,int len) {
for(int i=0;i<len;++i)
for(int j=0;j<len;++j)
A[x+i][y+j]=A[i][j];
}
void print(int x) {
for(int i=0;i<(1<<x);++i) {
for(int j=0;j<(1<<x);++j)
printf("%c",A[i][j]?'C':'P');
printf("\n");
}
}
void calc(int n) {
if(n==0) return A[0][0]=1,void();
calc(n-1);
int len=1<<(n-1);
copp(0,len,len);
copp(len,len,len);
for(int i=0;i<len;++i)
for(int j=0;j<len;++j)
A[len+i][j]=A[i][j]^1;
}
int main() {
int T;
cin>>T;
while(T-->0) {
int x;cin>>x;
calc(x);
print(x);
}
}

6709 Fishing Master

补充:看到zhihu好多全局钓鱼的,其实不难吧。

考虑dp,不会。贪心。

首先一开始肯定要先捉一次鱼。

发现捉鱼分两种种。

1.煮鱼的时间内能去捉鱼并且在锅里鱼没熟之前回来。

2.煮鱼的时间内能去捉鱼并且在锅里鱼熟之后时候回来。

显然1这种情况能干就干,相当于一开始就捉到了这些条。

剩下的捕鱼就得是情况2了,因为剩下的煮鱼时间都是小于捕鱼时间的,当然是贪心的从煮鱼时间大的开始捉。

发现这样一定能安排上(先捉情况2,然后过程中能捉1就捉1)。

然后就做完了。

#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
const int _=2e5+7;
ll n,m,t[_];
int main() {
std::ios::sync_with_stdio(false);
ll T;
cin>>T;
while(T --> 0) {
cin>>n>>m;
for(ll i=1;i<=n;++i) cin>>t[i];
sort(t+1,t+1+n);
ll ma=0,ans=0;
for(ll i=1;i<=n;++i) ma+=t[i]/m;
for(ll i=1;i<=n;++i) ans+=t[i];
ans+=m;
if(ma>=n-1) {
cout<<ans<<"\n";
} else {
ll need=n-1-ma;
for(ll i=1;i<=n;++i) t[i]-=t[i]/m*m;
sort(t+1,t+1+n);
for(ll i=n;i>=1;--i) {
need--;
ans+=m-t[i];
if(!need) break;
}
cout<<ans<<"\n";
}
}
}

2019CCPC网络预选赛 八道签到题题解的更多相关文章

  1. hpuoj--1695--一道签到题(KMP)

    1695: 一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 72  解决: 36 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过 ...

  2. 2018ICPC网络赛(焦作站)E题题解

    一.题目链接 二.题意 给定一棵树,有四种操作: $1\ u\ v\ x$:把节点$u$到$v$路径上的所有点的权值乘以$x$: $2\ u\ v\ x$:把节点$u$到$v$路径上的所有点的权值加上 ...

  3. 2019CCPC网络预选赛 1003 K-th occurrence 后缀自动机 + 二分 + 主席树

    题意:给你一个长度为n的字符串,有m次询问,每次询问l到r的子串在原串中第k次出现的位置,如果没有输出-1.n, m均为1e5级别. 思路:后悔没学后缀数组QAQ,其实只要学过后缀数组这个题还是比较好 ...

  4. 2019CCPC网络预选赛 1004 path 最短路

    题意:给你一张n个点m条边的有向图,问这张有向图的所有路径中第k短的路径长度是多少?n, m, k均为5e4级别. 思路:前些日子有一场div3的F和这个题有点像,但是那个题要求的是最短路,并且k最大 ...

  5. 2018ICPC网络赛(焦作站)K题题解

    一.题目链接 https://nanti.jisuanke.com/t/31720 二.题意 给$N$种船只,第$i$种船的载重量是$V_i$,数量是$2^{C_i}-1$.接下来有$Q$次询问,每次 ...

  6. 2018ICPC网络赛(徐州站)A题题解

    一.题目链接 https://nanti.jisuanke.com/t/31453 二.题意 给定$N$个位置,$2^k$种颜色,让你去涂色,条件是相邻的两种颜色类型异或值的二进制表示不全为$1$(以 ...

  7. 汤姆大叔的6道javascript编程题题解

    看汤姆大叔的博文,其中有篇(猛戳这里)的最后有6道编程题,于是我也试试,大家都可以先试试. 1.找出数字数组中最大的元素(使用Math.max函数) var a = [1, 2, 3, 6, 5, 4 ...

  8. 2019南昌邀请赛网络预选赛 M. Subsequence

    传送门 题意: 给出一个只包含小写字母的串 s 和n 个串t,判断t[i]是否为串 s 的子序列: 如果是,输出"YES",反之,输出"NO": 坑点: 二分一 ...

  9. 『ACM C++』Virtual Judge | 两道基础题 - The Architect Omar && Malek and Summer Semester

    这几天一直在宿舍跑PY模型,学校的ACM寒假集训我也没去成,来学校的时候已经18号了,突然加进去也就上一天然后排位赛了,没学什么就去打怕是要被虐成渣,今天开学前一天,看到最后有一场大的排位赛,就上去试 ...

随机推荐

  1. SpringMVC_处理器方法的返回值

    一.返回ModelAndView    若处理器方法处理完后,需要跳转到其他资源,且又要在跳转的资源间传递数据,此时处理器方法返回ModelAndView比较好.当然,若要返回ModelAndView ...

  2. tensorflow之tf.squeeze()

    tf.squeeze()函数的作用是从tensor中删除所有大小(szie)是1的维度. 给定丈量输入, 此操作返回的是相同类型的张量, 并删除所有尺寸为1的维度.如果不想删除所有尺寸为1的维度, 可 ...

  3. Python getopt 模块

    Python getopt 模块 getopt模块,是配合sys.argv使用的一个扩展.他可以接收终端的参数.格式扩展为“-n” 或 “--n”两种类型,下面是具体解释. 使用 improt get ...

  4. 基于OceanStor Dorado V3存储之数据保护 Hyper 特性

    基于OceanStor Dorado V3存储之数据保护 Hyper 特性 1.1  快照 1.2  HyperCDP 1.3  HyperCopy 1.4  克隆(HyperClone) 1.5   ...

  5. 【机器学习】PCA

    目录 PCA 1. PCA最大可分性的思想 2. 基变换(线性变换) 3. 方差 4. 协方差 5. 协方差矩阵 6. 协方差矩阵对角化 7. PCA算法流程 8. PCA算法总结 PCA PCA 就 ...

  6. vue入门案例

    1.技术在迭代,有时候你为了生活没有办法,必须掌握一些新的技术,可能你不会或者没有时间造轮子,那么就先把利用轮子吧. <!DOCTYPE html> <html> <he ...

  7. .NetCore+WebUploader实现大文件分片上传

    项目要求通过网站上传大文件,比如视频文件,通过摸索实现了文件分片来上传,然后后台进行合并. 使用了开源的前台上传插件WebUploader(http://fex.baidu.com/webupload ...

  8. Winform中设置ZedGraph因设置小刻度导致的竖直虚线显示过多

    场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  9. 高效并发一 Java内存模型与Java线程(绝对干货)

    高效并发一 Java内存模型与Java线程 本篇文章,首先了解虚拟机Java 内存模型的结构及操作,然后讲解原子性,可见性,有序性在 Java 内存模型中的体现,最后介绍先行发生原则的规则和使用. 在 ...

  10. redis笔记2

    分布式锁的实现 锁是用来解决什么问题的; 一个进程中的多个线程,多个线程并发访问同一个资源的时候,如何解决线程安全问题. 一个分布式架构系统中的两个模块同时去访问一个文件对文件进行读写操作 多个应用对 ...