之前没有做过字典树……感觉这个题字典树也能做……就拿来练一练字典树……板子好多地方写的都不够好,还需要继续改……
emmm这个……卡了好久啊……不过好在还是debug出来了……orz
虽然是处理后缀的问题,但是只需要reverse一下就可以变成前缀问题了2333333,然后每一次的字符串都插进去,最后从叶子到根遍历输出就可以了……
不过我好像……连叶子到根的遍历都写不好呜呜呜……ps:这里只是为了用trie而用trie……其实用map维护一下直接暴力求解就可以……
//trie树 /*1. 字符串检索 2.词频统计 3.字符串排序 先序遍历 4.前缀匹配 */ #include<bits/stdc++.h> using namespace std; const int MAX=10; string number; int now,cnt=0; int crt[25]; struct trie{ trie *next[MAX]; int v=0; }; trie *root[20]; trie* creat_trie() { trie *temp=(trie*)malloc(sizeof(trie)); for(int i=0;i<10;i++) temp->next[i]=NULL; return temp; } void insert_trie(trie *r,string s,int k) { trie *p=r; for(int i=0;i<s.length();i++) { int id=s[i]-‘0‘; if(p->next[id]==NULL) p->next[id]=creat_trie(); p=p->next[id]; } } void search_trie(trie *r,int k) { int c=0; for(int i=0;i<10;i++) { if(r->next[i]!=NULL) { c++; search_trie(r->next[i],k); } } if(c==0&&r->v!=-1) { crt[k]++; r->v=-1; } } void print(trie *r) { if(r->v==-1) { reverse(number.begin(),number.end()); cout<<number<<" "; reverse(number.begin(),number.end()); return ; } for(int i=0;i<10;i++) { if(r==root[now]) number=""; if(r->next[i]!=NULL) { number+=char(i+‘0‘); print(r->next[i]); number=number.substr(0,number.length()-1); } } } int main() { int n,m; map<string,int>e; string a,b; cin>>n; memset(crt,0,sizeof(crt)); for(int i=0;i<=n;i++) root[i]=creat_trie(); while(n--) { cin>>a; if(e[a]==0) e[a]=++cnt; cin>>m; now=e[a]; while(m--) { cin>>b; reverse(b.begin(),b.end()); insert_trie(root[now],b,now); } } cout<<e.size()<<endl; map<string,int>::iterator it; for(it=e.begin();it!=e.end();it++) { cout<<it->first<<" "; now=it->second; search_trie(root[now],now); cout<<crt[now]<<" "; print(root[now]); cout<<endl; } return 0; }
(好像还有个后缀树啥的……emmmm还没有学习……码着先)
是个前缀和+贪心的问题么……看大佬简洁的代码是那么处理的,自己搞得太复杂了……还……好多bug
需要好好想想哪些用前缀和处理更简洁,比如像这种多长时间内的,多大长度内的问题,可以考虑用前缀和?
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n,m,k,b; ll a[1000005]; int main() { cin>>n>>m>>k; memset(a,0,sizeof(a)); for(int i=0;i<n;i++) { cin>>b; a[b]=1; } int ans=0; for(int i=1;i<=m;i++) { a[i]+=a[i-1]; if(a[i]>=k) { ans+=(a[i]-(k-1)); a[i]=k-1; } } for(int i=m+1;i<1e6+5;i++) { a[i]+=a[i-1]; b=a[i]-a[i-m]; if(b>=k) { ans+=(b-k+1); a[i]=a[i-m]+k-1; } } cout<<ans<<endl; return 0; }
想着暴力dfs我也是傻了……orz
依旧还是贪心,这次题……好多贪心……
2种情况……为平方数的个数m<=n/2,ans=(n/2-m)个非平方数变成平方数和的最小值
m>=n/2,ans=(m-n/2)个平方数变为非平方数和的最小值(非0值每个数只需要+1,0需要+2)//注意0需要特判,良心样例有没有啊!
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n,a[200005],ans; ll b[200005]; int main() { cin>>n; int cnt=0,cnt0=0,cnt1=0; for(int i=0;i<n;i++) { cin>>a[i]; ll c=sqrt(a[i]); ll minn=min(a[i]-pow(c,2),pow(c+1,2)-a[i]); b[i]=minn; if(b[i]==0) cnt++; if(a[i]==0) cnt0++; } if(cnt>=n/2&&cnt0<=n/2) ans=cnt-n/2; else if(cnt0>n/2) ans=cnt-cnt0+2*(cnt0-n/2); else { ans=0; sort(b,b+n); for(int i=0;i<n/2;i++) ans+=b[i]; } cout<<ans<<endl; return 0; }