cf806dv4 806dv2

Dashboard - Codeforces Round #806 (Div. 4) - Codeforces

题意:给出多个字符串,问能被其它字符串拼凑则这一个串记作1否则记作0

正解:因为字符串长度最多为8,substr枚举一下就好
void solved()
{
    int n;cin>>n;
 
    map<string,int>mp;
    for(int i=1;i<=n;i++)
    {
        cin>>str[i];
        mp[str[i]]++;
    }
    for(int i=1;i<=n;i++)
    {
        bool ok=0;
        string s=str[i];
        for(int i=1;i<=s.size()-1;i++)
        {
            string a=s.substr(0,i),b=s.substr(i,s.size()-1);
        if(mp[a]&&mp[b])ok=1;
        }
        
        if(ok)cout<<1;
        else cout<<0;
    }
    puts("");
}

中心对称,思路简单,主要看代码实现

以下给出顺序遍历时 中心对称的坐标
a=mp[i][j],b=mp[j][n-i+1],尤其前两项90度旋转就已经可以好好利用了

c=mp[n-i+1][n-j+1],d=mp[n-j+1][i];

char mp[110][110];
bool vis[110][110];
void solved()
{
    memset(vis,0,sizeof vis);
    int n;cin>>n;
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     cin>>mp[i][j];
 
    int ans=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        char a=mp[i][j],b=mp[j][n-i+1],c=mp[n-i+1][n-j+1],d=mp[n-j+1][i];
        if(vis[i][j])continue;
        vis[i][j]=1,vis[j][n-i+1]=1,vis[n-i+1][n-j+1]=1,vis[n-j+1][i]=1;
        int aa=0,bb=0;
        if(a=='0')aa++;else bb++;
        if(b=='0')aa++;else bb++;
        if(c=='0')aa++;else bb++;
        if(d=='0')aa++;else bb++;
        ans+=min(aa,bb);
    }
    cout<<ans<<'\n';
}

题意:统计i<a[i]<j<a[j]的对数

正解:先处理i<a[i]
接下来只要找a[j]>i

暴力还是会超,这里考虑树状数组or直接前缀和,二分来做

只讲树状数组
只要查询每个a[i]和树状数组中计数的i的关系就行add(i,1)
模拟知query到的会是1到a[i],我们要求小于a[i],因此query a[i]-1
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int k)
{
    while(x<=n)
    {
        tr[x]+=k;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=tr[x];
        x-=lowbit(x);
    }
    return ans;
}
 
int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        ll ans=0;
        mem(tr,0);
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            if(a[i]<i)
            {
				add(i,1);
                ans+=sum(a[i]-1);
             
            }
        }
        cout<<ans<<endl;
    }

题意:好钥匙花费费用,坏钥匙不花费费用,但是所有箱子价值减半,可以无限欠费,求打开箱子得到费用求最大费用

一眼Dp
可以贪心做:先选好钥匙,再选坏钥匙
证明:第一次欠费,(a[i]+a[i+1])/2>a[i]+a[i+1]/2不可能成立
ll ans,s[maxn],ANS,k,m[40]={1};
int main(){
	for(int i=1;i<=33;i++) m[i]=m[i-1]*2ll;
	cin>>t;
	while(t--){
	cin>>n>>k;
	ll res=-1;
	for(int i=1;i<=n;i++) cin>>a[i], s[i]=s[i-1]+a[i];
	for(int x=0;x<=n;x++){
		ans=s[x]-k*1ll*x; 
		for(int i=x+1;i<=min(x+32,n);i++) ans+=a[i]/m[i-x];
		res=max(res,ans);
	}
	cout<<res<<endl;
	}

Dashboard - Codeforces Round #807 (Div. 2) - Codeforces

dv2

一维排序,站成两排,以+n对应就Ok不用转二维
void solved()
{  
    int n,x;cin>>n>>x;
	int g[10][110];
	int q[110];
	for(int i=1;i<=2*n;i++)cin>>q[i];
	sort(q+1,q+2*n+1);
	int cnt=0;
	for(int i=1;i<=2;i++)
	{
		for(int j=1;j<=n;j++)
		g[i][j]=q[++cnt];
	}
	
	bool ok=1;
	for(int i=1;i<=2;i++)
	{
		for(int j=1;j<=n;j++)
		if(g[1][j]+x>g[2][j]){puts("NO");return;}
	}
	puts("YES");
}

思维有0就补上,否则都需要清空掉即算作计数
void solved()
{  
    ll n;cin>>n;
		ll ans=0;
	for(int i=1;i<=n;i++)cin>>q[i];
	for(int i=1;i<n-1;i++)
		if(q[i]&&!q[i+1])q[i]-=1,q[i+1]=1,ans++;
	
 
	for(int i=1;i<n;i++)
	ans+=q[i];
	cout<<ans<<'\n';
}
题意:每次复制字符串接在前一个字符串后面,查询第k个字符

本题是活用了数组

存直接用c次去存
找就从最后一层往回找
ll n,c,q;
void solved()
{  
    cin>>n>>c>>q;
    string ss;cin>>ss;ss=" "+ss;
    int len=ss.size()-1;
    ll s[40],l[40],r[40];
    s[0]=len;
 
    for(int i=1;i<=c;i++)
    {
        ll x,y;cin>>x>>y;
        
        复制的左右界
        l[i]=x,r[i]=y;
        
        串的当前长度
        s[i]=s[i-1]+y-x+1;
    }
 
    while(q--)
    {
        ll k;cin>>k;

        二分k找是s中的哪一次复制
        while(k>s[0])
        {
            二分左端点s,右s+c+1,-s返回下标(不然会是地址)
            ll x=lower_bound(s,s+c+1,k)-s;
            
            更新k直到初始字符串
            
             看K在从l开始的哪里,-1是l[x]占了一项
            k=l[x]+k-s[x-1]-1;
        }
        cout<<ss[k]<<'\n';
    }
}

题意:s串能否变成t串,操作只能选i+1,i-1,必须不同,改变i
连续的1,0块个数相同,首尾串相同,才能合题意

移动次数找规律,模拟,是存的下标差

ll n;
string s,t;
void solve(){
	cin>>n;
	cin>>s>>t;
	vector<int> a,b;
	for(int i=0;s[i];i++){
		if(s[i]!=s[i+1]) a.pb(i);
		if(t[i]!=t[i+1]) b.pb(i);
	}
	if(a.size()!=b.size()||s[0]!=t[0]||s[n-1]!=t[n-1]){
		cout<<-1<<endl;
		return;
	}
	ll ans=0;
	for(int i=0;i<a.size();i++){
		ans+=abs(a[i]-b[i]);
	}
	cout<<ans<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值