题目链接:https://vjudge.net/contest/348944#overview
A:CodeForces 1255C
题意:给你n-2个打乱顺序的三元组序列,让你排出原序列。
思路:哇,这题思路很明显啊,不过说实话代码好难敲呀。首先找出现一次的,然后在其中确定出现两次的出现三次的,把他们都标记一下,再以这两个去确定剩下的那个未被标记元素,找到n个就结束了。我的代码蛮丑的,不知道咋优化的。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+9;
const int mod = 1e9+7;
int a[N],mp[N],cnt[N];
int h[N][4];
int vis[N];
map<pair<int,int> ,int>mp1;
map<pair<int,int> ,int>mp2;
int main(){
int n;
cin>>n;
for(int i=1;i<=n-2;i++){
int aa,bb,cc;
cin>>aa>>bb>>cc;
h[i][0]=aa,h[i][1]=bb,h[i][2]=cc;
mp[aa]=i,mp[bb]=i,mp[cc]=i;
cnt[aa]++,cnt[bb]++,cnt[cc]++;
if(mp1.count({aa,bb}))mp2[{aa,bb}]=cc;
else mp1[{aa,bb}]=cc;
if(mp1.count({bb,aa}))mp2[{bb,aa}]=cc;
else mp1[{bb,aa}]=cc;///a,b
if(mp1.count({aa,cc}))mp2[{aa,cc}]=bb;
else mp1[{aa,cc}]=bb;
if(mp1.count({cc,aa}))mp2[{cc,aa}]=bb;
else mp1[{cc,aa}]=bb;///a,c
if(mp1.count({bb,cc}))mp2[{bb,cc}]=aa;
else mp1[{bb,cc}]=aa;
if(mp1.count({cc,bb}))mp2[{cc,bb}]=aa;
else mp1[{cc,bb}]=aa;///b.c
}
int st;
for(int i=1;i<=n;i++){
if(cnt[i]==1){
st=i;break;
}
}
int p,q;
vector<int>v;
for(int i=0;i<3;i++){
int fq=mp[st];
if(cnt[h[fq][i]]==2){
p=h[fq][i];
}
if(cnt[h[fq][i]]==3){
q=h[fq][i];
}
}
v.push_back(st);vis[st]=1;
v.push_back(p);vis[p]=1;
v.push_back(q);vis[q]=1;
int t=n-3;
while(t--){
int s1=mp1[{p,q}];
int s2=mp2[{p,q}];
if(!vis[s1]){
p=q,q=s1;vis[s1]=1;
v.push_back(s1);
}
else{
p=q,q=s2;vis[s2]=1;
v.push_back(s2);
}
}
for(auto ss:v)cout<<ss<<" ";cout<<endl;
}
**
B:HDU 1698
**
题意不表
思路:线段树lazy标记的裸题,emmm还是推荐一下文章OI大佬们的GitHub项目
https://oi-wiki.org/ds/seg/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+9;
struct node{
int l,r;
ll data,add;
}m[N<<2];
ll a[N];
void pushdown(int rt,int len){
if(m[rt].add){
m[rt<<1].add=m[rt].add;
m[rt<<1|1].add=m[rt].add;
m[rt<<1].data=m[rt].add*((ll)len-(len>>1));
m[rt<<1|1].data=m[rt].add*((ll)len>>1);
m[rt].add=0;
}
}
void build(int rt,int l,int r){
m[rt].l=l;
m[rt].r=r;
m[rt].add=0;
if(l==r){
m[rt].data=1;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
m[rt].data=m[rt<<1].data+m[rt<<1|1].data;
}
void update(int l,int r,ll v,int rt){
if(l<=m[rt].l&&r>=m[rt].r){
m[rt].add=v;
m[rt].data=v*(m[rt].r-m[rt].l+1ll);
return;
}
pushdown(rt,m[rt].r-m[rt].l+1);
int mid=(m[rt].r+m[rt].l)>>1;
if(mid>=l)update(l,r,v,rt<<1);
if(mid<r)update(l,r,v,rt<<1|1);
m[rt].data=m[rt<<1|1].data+m[rt<<1].data;
}
int main(){
int t,cas=1;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
build(1,1,n);
int q;
scanf("%d",&q);
while(q--){
int x,y;ll z;
scanf("%d%d%lld",&x,&y,&z);
update(x,y,z,1);
}
printf("Case %d: The total value of the hook is %lld.\n"
,cas++,m[1].data);
}
}
C:CodeForces 1272D
题意:删一个数或者不删使上升序列最长,找出最长。
思路:由于dp还是非常的不熟,所以本题采用的是基础方法。
把每一段上升的序列放到vector然后找把前一个的尾巴和后一个头比较看一下能删哪个,然后找出最长的那个。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9;
int a[N];
vector<int>v[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int m=0;v[m].push_back(a[1]);
for(int i=2;i<=n;i++){
if(a[i]>a[i-1]){
v[m].push_back(a[i]);
}
else{
v[++m].push_back(a[i]);
}
}
int maxv=-1;
for(int i=0;i<=m;i++){
int q=v[i].size();
maxv=max(q,maxv);
}
for(int i=1;i<=m;i++){
int x=v[i-1].size()-1,y=v[i].size()-1;
if(v[i-1][x]<v[i][1]||v[i-1][x-1]<v[i][0]){
maxv=max(x+y+1,maxv);
}
}
cout<<maxv<<endl;
}
D:HDU 1255
线段树扫描线的应用,待补
E:CodeForces 1281B
题意:第一个字符串换一个字符,看看能否小于第二个
思路:每次找字典序最小的字符,如果有一个不在靠前的地方就找到交换最后面的那个,如果没有,再继续找。
#include<bits/stdc++.h>
using namespace std;
const int N = 5e3+9;
const int mod = 1e9+7;
int s[N];
int main(){
int t;
cin>>t;
while(t--){
string a,b;
cin>>a>>b;
if(a<b){
cout<<a<<endl;
}
else{
string tp;
for(int i=0;i<a.size();i++){
s[i]=a[i]-'A';
}
int st=0,suc=1;
while(1){
int mini=0x3f3f3f3f;
for(int i=st;i<a.size();i++){
mini=min(mini,s[i]);
}
s[a.size()]=1000;
while(s[st]==mini){
st++;
}
if(st>=a.size()){
suc=0;break;
}int flag=0;
for(int i=a.size()-1;i>st;i--){
if(s[i]==mini){
flag=1;swap(s[st],s[i]);
break;
}
}
if(flag)break;
}
for(int i=0;i<a.size();i++){
char ss=s[i]+'A';
tp+=ss;
}
if(tp>=b)cout<<"---"<<endl;
else{
cout<<tp<<endl;
}
}
}
}
F:CodeForces - 1280A
题意:就是光标移动+光标后的复制光标前最后一个数字的次数
思路:最后补的题,允许范围内模拟,范围外计算。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e7+9;
char s[N];
int main(){
int t;
cin>>t;
while(t--){
int n,flg=0;ll ans=0,l=0;
scanf("%d %s",&n,s);
ans=l=(ll)strlen(s);
for(int ct=1;ct<=n;ct++){
int k=s[ct-1]-'0';
if(l<=n){
for(int i=1;i<k;i++){
for(int j=ct;j<ans;j++){
s[l++]=s[j];
}
}
}
ans=((ans-ct+mod)*k%mod+ct%mod)%mod;
}
cout<<ans<<endl;
}
}