C - Recover an RBS
一开始的思路就像错了,我一直从?的个数来入手,但这样考虑的情况好像有点多,昨天写了半天也写不对,今天看题解之后原来只要把该填的填好之后,交换最近的一对括号看看是否还合法即可
Educational Codeforces Round 132 (Rated for Div. 2) A - E - 知乎 (zhihu.com)
#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const ll mod=1e9+7;
ll t;
string s;
int main(){
cin>>t;
while(t--){
cin>>s;
ll l=0,r=0,n=s.size();
for(int i=0;i<s.size();i++){
if(s[i]=='(') l++;
else if(s[i]==')') r++;
}
if(l==n/2||r==n/2){printf("YES\n");continue;}
ll maxl=0,minr=s.size(),left=n/2-l,sum=0;
for(ll i=0;i<s.size();i++){
if(s[i]=='?'){
if(left) s[i]='(',left--,maxl=max(maxl,i);
else s[i]=')',minr=min(minr,i);
}
}
swap(s[maxl],s[minr]);
bool flag=0;
for(int i=0;i<s.size();i++){
if(s[i]=='(') sum++;
else sum--;
if(sum<0){
flag=1;break;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
system("pause");
return 0;
}
1621B - Integers Shop
这个题目写的好糟心,写了一上午也没有调出来,心态炸了,大体思路很好想,但是实现的思路没想明白,太弱了,,,
codeforces1621B Integers Shop(贪心)_YounCGY的博客-CSDN博客
#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const ll mod=1e9+7;
ll t,n;
ll c[100005],l[100005],r[100005];
int main(){
cin>>t;
while(t--){
ll L=1e18,R=0,minl=1e18,minr=1e18,minlr=1e18;
cin>>n;
for(int i=1;i<=n;i++){
cin>>l[i]>>r[i]>>c[i];
if(L>l[i]){L=l[i];minl=1e18;minlr=1e18;}
if(R<r[i]){R=r[i];minr=1e18;minlr=1e18;}
if(L==l[i]) minl=min(minl,c[i]);
if(R==r[i]) minr=min(minr,c[i]);
if(L==l[i]&&R==r[i]) minlr=min(minlr,c[i]);
//cout<<L<<" "<<R<<" "<<minl<<" "<<minr<<" "<<minlr<<endl;
printf("%lld\n",min(minlr,minl+minr));
}
}
system("pause");
return 0;
}
1462E1 - Close Tuples (easy version)
要注意选三个数的六种情况,别的没啥了
#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const ll mod=1e9+7;
ll t,n,a[200005],tx[200005],sum[200005];
int main(){
cin>>t;
sum[0]=sum[1]=sum[2]=0;
for(ll i=3;i<200005;i++) sum[i]=sum[i-1]+(i-2LL)*(i-1LL)/2LL;
//for(int i=3;i<=6;i++) cout<<i<<" "<<sum[i]<<endl;
while(t--){
scanf("%lld",&n);
for(int i=1;i<=n+10;i++) tx[i]=0;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),tx[a[i]]++;
ll ans=0;
for(int i=1;i<=n;i++){
ans+=sum[tx[i]]+
((tx[i]-1)*(tx[i])/2)*tx[i+1]+
tx[i]*((tx[i+1]-1)*(tx[i+1])/2)+
((tx[i]-1)*(tx[i])/2)*tx[i+2]+
tx[i]*((tx[i+2]-1)*(tx[i+2])/2)+
tx[i]*tx[i+1]*tx[i+2];
}
printf("%lld\n",ans);
}
system("pause");
return 0;
}
P1265 公路修建 - 洛谷 prim
其实第二条是没有用的,题目中说的是每个城市都会选择与自己相近的城市,第二条也就是说每个城市选择与自己相近的城市构成环,但明显这是不对的,只有等边多边形才适合,但题目说有唯一解,所以也没有多边形,去掉这条就是最小生成树了,但是边太多,应该使用prim
#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const ll mod=1e9+7;
ll n,vis[5005];
double d[5005];
struct node{
double x,y;
}c[5005];
double dis(node a,node b){
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
void prim(){
ll x=0;
for(int i=0;i<=n;i++) vis[i]=0,d[i]=1e18;
d[1]=0;
for(int i=1;i<=n-1;i++){
x=0;
for(int j=1;j<=n;j++){
if(!vis[j]&&(!x||d[j]<d[x])) x=j;
}
vis[x]=1;
for(int j=1;j<=n;j++){
if(!vis[j]) d[j]=min(d[j],dis(c[x],c[j]));
}
}
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf",&c[i].x,&c[i].y);
prim();
double ans=0;
//for(int i=1;i<=n;i++) cout<<d[i]<<" "<<i<<endl;
for(int i=1;i<=n;i++) ans+=d[i];
printf("%.2f\n",ans);
system("pause");
return 0;
}
P1340 兽径管理 - 洛谷 | 最小生成树逆序
这题感觉正着跑会超时啊,但题解里面很多都是正着跑的,可能我复杂度估计错了,,,但是逆序跑更稳,再说一个绿题正着跑也太水了,,,把他倒着跑,如果这个边是后面天数的就不能用了,需要再跑一遍最小生成树,否则就可以不重新跑一遍,这样就减少了跑生成树的次数,减少了点时间复杂度,used标记的是参与最小生成树的边,vis标记的是不能用的边
题解 P1340 【兽径管理】 - SovietPower✨ 的博客 - 洛谷博客
#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const ll mod=1e9+7;
ll n,w,s[205],vis[6005],used[6006];
struct node{
ll u,v,w,id;
bool operator<(const node& a)const { return w<a.w; }
}ed[6005],e[6005];
ll findd(ll x){return x==s[x]?x:s[x]=findd(s[x]);}
ll kruscal(){
ll ans=0;
ll cnt=0;
for(int i=1;i<=n;i++) s[i]=i;
for(int i=1;i<=w;i++) used[i]=0;
for(int i=1;i<=w;i++){
if(vis[ed[i].id]) continue;
ll xx=findd(ed[i].u),yy=findd(ed[i].v);
if(xx==yy) continue;
s[xx]=yy;used[ed[i].id]=1;
ans+=ed[i].w;cnt++;
if(cnt>=n-1) return ans;
}
return -1;
}
ll ans[6005];
int main(){
scanf("%lld%lld",&n,&w);
//cout<<n<<" "<<w<<endl;
for(int i=1;i<=w;i++){
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
ed[i].u=u;ed[i].v=v;ed[i].w=w;ed[i].id=i;
}
sort(ed+1,ed+w+1);
ll flag=1;
ans[w]=kruscal();
vis[w]=1;
for(int i=w-1;i>=1;i--){
// cout<<i<<" "<<used[i+1]<<endl;
if(flag==0){
ans[i]=-1;continue;
}
if(used[i+1]){
//cout<<"ssssss "<<i<<endl;
ans[i]=kruscal();if(ans[i]==-1) flag=0;
}
else ans[i]=ans[i+1];
vis[i]=1;
}
for(int i=1;i<=w;i++) printf("%lld\n",ans[i]);
system("pause");
return 0;
}
P1351 [NOIP2014 提高组] 联合权值 - 洛谷 | dfs
标签写的是lca,但自己用dfs做了出来,,,距离为2的才有联合权值也就是一个点只有和本身的爷爷以及兄弟才有联合权值,那么爷爷的联合权值很好求,只需要一个父亲数组f就可以,兄弟的也可以o(n)的求出来,一个点与兄弟的联合权值等于该点的权值*(下一个兄弟一直到最后一个兄弟的和),求个前缀和就可以,最大值那就是枚举最大的两个兄弟权值的乘积,需要注意的是一定是要在dfs后执行求前缀和和求兄弟的操作,不然进入dfs后一切都乱了
#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const ll mod=10007;
ll n,f[200005],c[200005],vsu[200005];
vector<ll>v[200005];
ll maxx=0,sum=0;
void dfs(ll u,ll fa){
f[u]=fa;
if(f[fa]){
maxx=max(maxx,c[f[fa]]*c[u]);
sum=(sum+c[u]*c[f[fa]]*2LL%mod)%mod;
}
for(int i=0;i<v[u].size();i++){
ll j=v[u][i];
if(j==fa) continue;
dfs(j,u);
}
for(int i=1;i<=v[u].size()+10;i++) vsu[i]=0;
for(int i=0;i<v[u].size();i++){
vsu[i+1]=vsu[i];
ll j=v[u][i];
if(j==fa) continue;
vsu[i+1]+=c[j];
}
ll max1=0,max2=0;
for(int i=0;i<v[u].size();i++){
ll j=v[u][i];
if(j==fa) continue;
if(c[j]>max1){
max2=max1;max1=c[j];
}
else if(c[j]<=max1&&c[j]>max2){max2=c[j];}
//cout<<u<<" "<<i<<" "<<vsu[v[u].size()]<<" "<<vsu[i+1]<<" "<<(vsu[v[u].size()]-vsu[i])<<endl;
sum=(sum+c[j]*(vsu[v[u].size()]-vsu[i+1])*2LL%mod)%mod;
}
//cout<<u<<" "<<max1<<" "<<max2<<endl;
maxx=max(maxx,max1*max2);
}
int main(){
scanf("%lld",&n);
for(int i=1;i<n;i++){
ll u,vv;
scanf("%lld%lld",&u,&vv);
v[u].push_back(vv);
v[vv].push_back(u);
}
for(int i=1;i<=n;i++) scanf("%lld",&c[i]);
dfs(1,0);
printf("%lld %lld\n",maxx,sum);
system("pause");
return 0;
}