題目鏈接: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;
}
}